diff --git a/.gitignore b/.gitignore
index 903b4536..809a3161 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,11 +1,3 @@
-# downstream content
-_core
-_browser
-_android
-_ios
-_gaia
-
-
# OS or Editor folders
.DS_Store
node_modules
@@ -14,3 +6,5 @@ node_modules
_site
.sass-cache
.jekyll-metadata
+package-lock.json
+package.json
diff --git a/_android/.svn/entries b/_android/.svn/entries
new file mode 100644
index 00000000..48082f72
--- /dev/null
+++ b/_android/.svn/entries
@@ -0,0 +1 @@
+12
diff --git a/_android/.svn/format b/_android/.svn/format
new file mode 100644
index 00000000..48082f72
--- /dev/null
+++ b/_android/.svn/format
@@ -0,0 +1 @@
+12
diff --git a/_android/.svn/pristine/14/1495dab64473f038310e6601ebb6f0450c97a2af.svn-base b/_android/.svn/pristine/14/1495dab64473f038310e6601ebb6f0450c97a2af.svn-base
new file mode 100644
index 00000000..2eaccb4f
Binary files /dev/null and b/_android/.svn/pristine/14/1495dab64473f038310e6601ebb6f0450c97a2af.svn-base differ
diff --git a/_android/.svn/pristine/1e/1e84e69d0aeae9c31e35f2ba6dad3de414550ebf.svn-base b/_android/.svn/pristine/1e/1e84e69d0aeae9c31e35f2ba6dad3de414550ebf.svn-base
new file mode 100644
index 00000000..1be7edf5
Binary files /dev/null and b/_android/.svn/pristine/1e/1e84e69d0aeae9c31e35f2ba6dad3de414550ebf.svn-base differ
diff --git a/_android/.svn/pristine/2c/2c518a2d8710e880cc0fb87c202979c15c2b4cbe.svn-base b/_android/.svn/pristine/2c/2c518a2d8710e880cc0fb87c202979c15c2b4cbe.svn-base
new file mode 100644
index 00000000..b5e5c141
Binary files /dev/null and b/_android/.svn/pristine/2c/2c518a2d8710e880cc0fb87c202979c15c2b4cbe.svn-base differ
diff --git a/_android/.svn/pristine/41/410814802457e751ef97090c0813861c8e2234c9.svn-base b/_android/.svn/pristine/41/410814802457e751ef97090c0813861c8e2234c9.svn-base
new file mode 100644
index 00000000..081d5050
Binary files /dev/null and b/_android/.svn/pristine/41/410814802457e751ef97090c0813861c8e2234c9.svn-base differ
diff --git a/_android/.svn/pristine/53/53c6a58a4107359c52b61f15feda85eaea9fba81.svn-base b/_android/.svn/pristine/53/53c6a58a4107359c52b61f15feda85eaea9fba81.svn-base
new file mode 100644
index 00000000..1de35691
Binary files /dev/null and b/_android/.svn/pristine/53/53c6a58a4107359c52b61f15feda85eaea9fba81.svn-base differ
diff --git a/_android/.svn/pristine/5f/5fb343bd86c0ea238c08217aaa064a1d2cb08707.svn-base b/_android/.svn/pristine/5f/5fb343bd86c0ea238c08217aaa064a1d2cb08707.svn-base
new file mode 100644
index 00000000..62ae3f5d
Binary files /dev/null and b/_android/.svn/pristine/5f/5fb343bd86c0ea238c08217aaa064a1d2cb08707.svn-base differ
diff --git a/_android/.svn/pristine/6b/6bbb57e8973ee164a4f7dfb71fe008ad2b0776b3.svn-base b/_android/.svn/pristine/6b/6bbb57e8973ee164a4f7dfb71fe008ad2b0776b3.svn-base
new file mode 100644
index 00000000..914b26e5
Binary files /dev/null and b/_android/.svn/pristine/6b/6bbb57e8973ee164a4f7dfb71fe008ad2b0776b3.svn-base differ
diff --git a/_android/.svn/pristine/75/75758e4df03bd71c064433719414818a69d19709.svn-base b/_android/.svn/pristine/75/75758e4df03bd71c064433719414818a69d19709.svn-base
new file mode 100644
index 00000000..5e4d6256
Binary files /dev/null and b/_android/.svn/pristine/75/75758e4df03bd71c064433719414818a69d19709.svn-base differ
diff --git a/_android/.svn/pristine/83/832a38b5a0091b01fd469a28cd5c7299ed0895dc.svn-base b/_android/.svn/pristine/83/832a38b5a0091b01fd469a28cd5c7299ed0895dc.svn-base
new file mode 100644
index 00000000..601f3e8a
Binary files /dev/null and b/_android/.svn/pristine/83/832a38b5a0091b01fd469a28cd5c7299ed0895dc.svn-base differ
diff --git a/_android/.svn/pristine/85/85768bb09fc031d0d5770a7bab301dc61617ce8f.svn-base b/_android/.svn/pristine/85/85768bb09fc031d0d5770a7bab301dc61617ce8f.svn-base
new file mode 100644
index 00000000..d434f9bb
Binary files /dev/null and b/_android/.svn/pristine/85/85768bb09fc031d0d5770a7bab301dc61617ce8f.svn-base differ
diff --git a/_android/.svn/pristine/a1/a10d2160fb036c58a0e7e171b9ff8fd9652d3c06.svn-base b/_android/.svn/pristine/a1/a10d2160fb036c58a0e7e171b9ff8fd9652d3c06.svn-base
new file mode 100644
index 00000000..484d24fe
--- /dev/null
+++ b/_android/.svn/pristine/a1/a10d2160fb036c58a0e7e171b9ff8fd9652d3c06.svn-base
@@ -0,0 +1,773 @@
+---
+layout: learn
+permalink: /:collection/:path.html
+---
+# Android SDK Tutorial (Pre-release)
+{:.no_toc}
+
+This tutorial is written for readers who are new to either or both Blockstack
+and Android to create a decentralized application. It contains the following
+content:
+
+* TOC
+{:toc}
+
+This tutorial was extensively tested using Android Studio 3.1 on a MacBook Air
+running High Sierra 10.13.4. If your environment is different, you may encounter
+slight or even major discrepancies when performing the procedures in this
+tutorial. Please [join the Blockstack community
+Slack](https://slofile.com/slack/blockstack) and post questions or comments to
+the `#support` channel.
+
+Finally, this tutorial is written for all levels from the beginner to the most
+experienced. For best results, beginners should follow the guide as written. It
+is expected that the fast or furiously brilliant will skip ahead and improvise
+on this material at will. Fair journey one and all.
+
+If you prefer, you can skip working through the tutorial all together. Instead,
+you can [download the final project code](images/helloandroid.zip) and import it
+into Android Studio to review it.
+
+## Understand the sample application flow
+
+When complete, the sample application is a simple `hello-world` display. It is
+intended for user on an Android phone.
+
+![](images/final-app.png)
+
+Only users with an existing `blockstack.id` can run your
+final sample application. When complete, users interact with the sample
+application by doing the following:
+
+![](images/app-flow.png)
+
+## Set up your environment
+
+This sample application has two code bases, a Blockstack `hello-blockstack`
+application and a `hello-andriod` Android application. Before you start
+developing the sample, there are a few elements you need in your environment.
+
+### Install Android Studio
+
+If you are an experienced Android developer and already have an Android
+development environment on your workstation, you can use that and skip this
+step. However, you will need to adjust the remaining instructions for your
+environment.
+
+Follow the installation instructions to download and [Android Studio
+3.1](https://developer.android.com/studio/install) for your operating system.
+Depending on your network connection, this can take between 15-30 minutes.
+
+![](images/studio-download.png)
+
+### Do you have npm?
+
+The Blockstack code in this tutorial relies on the `npm` dependency manager.
+Before you begin, verify you have installed `npm` using the `which` command to
+verify.
+
+```bash
+$ which npm
+/usr/local/bin/npm
+```
+
+If you don't find `npm` in your system, [install
+it](https://www.npmjs.com/get-npm).
+
+### Install the Blockstack test rig
+
+Users interact with Blockstack-enabled applications through a web browser. You
+can Blockstack in test mode, on `localhost` or you can interact with completed
+apps through the Blockstack webapp which is available at
+[https://browser.blockstack.org/].
+
+If you have already installed Blockstack for testing locally and have an
+existing Blockstack ID, skip this section. Otherwise, continue onto install
+Blockstack.
+
+1. Go to [Blockstack](https://blockstack.org/install)
+
+ ![](images/blockstack-install.png)
+
+2. Install the version appropriate for your operating system.
+
+
+### Use npm to install Yeoman and the Blockstack App Generator
+
+You use `npm` to install Yeoman. Yeoman is a generic scaffolding system that
+helps users rapidly start new projects and streamline the maintenance of
+existing projects.
+
+
+1. Install Yeoman.
+
+ ```bash
+ npm install -g yo
+ ```
+2. Install the Blockstack application generator.
+
+ ```bash
+ npm install -g generator-blockstack
+ ```
+
+
+## Build the Blockstack hello-world
+
+In this section, you build a Blockstack `hello-world` application. Then, you
+modify the `hello-world` to interact with the Android app via a redirect.
+
+### Generate and launch your hello-blockstack application
+
+In this section, you build an initial React.js application called
+`hello-blockstack`.
+
+1. Create a `hello-blockstack` directory.
+
+ ```bash
+ mkdir hello-blockstack
+ ```
+
+2. Change into your new directory.
+
+ ```bash
+ cd hello-blockstack
+ ```
+
+3. Use Yeoman and the Blockstack application generator to create your initial `hello-blockstack` application.
+
+ ```bash
+ yo blockstack:react
+ ```
+
+ You should see several interactive prompts.
+
+ ```bash
+ $ yo blockstack:react
+ ==========================================================================
+ We are constantly looking for ways to make yo better!
+ May we anonymously report usage statistics to improve the tool over time?
+ More info: https://github.com/yeoman/insight & http://yeoman.io
+ ========================================================================== No
+
+ _-----_ ╭──────────────────────────╮
+ | | │ Welcome to the │
+ |--(o)--| │ Blockstack app │
+ --------- │ generator! │
+ ( _U_ ) ╰──────────────────────────╯
+ /___A___\ /
+ | ~ |
+ __'.___.'__
+ |° Y
+
+ ? Are you ready to build a Blockstack app in React? (Y/n)
+ ```
+
+4. Respond to the prompts to populate the initial app.
+
+ After the process completes successfully, you see a prompt similar to the following:
+
+ ```bash
+ [fsevents] Success:
+ "/Users/theuser/repos/hello-blockstack/node_modules/fsevents/lib/binding/Release/node-v59-darwin-x64/fse.node"
+ is installed via remote npm notice created a lockfile as package-lock.json.
+ You should commit this file. added 1060 packages in 26.901s
+ ```
+
+5. Run the initial application.
+
+ ```bash
+ $ npm start
+
+ > hello-blockstack@0.0.0 start /Users/moxiegirl/repos/hello-blockstack
+ > webpack-dev-server
+
+ Project is running at http://localhost:8080/
+ webpack output is served from /
+ 404s will fallback to /index.html
+ Hash: 4d2312ba236a4b95dc3a
+ Version: webpack 2.7.0
+ Time: 2969ms
+ Asset Size Chunks Chunk Names
+ ....
+ Child html-webpack-plugin for "index.html":
+ chunk {0} index.html 541 kB [entry] [rendered]
+ [0] ./~/lodash/lodash.js 540 kB {0} [built]
+ [1] ./~/html-webpack-plugin/lib/loader.js!./src/index.html 533 bytes {0} [built]
+ [2] (webpack)/buildin/global.js 509 bytes {0} [built]
+ [3] (webpack)/buildin/module.js 517 bytes {0} [built]
+ webpack: Compiled successfully.
+ ```
+
+ The system opens a browser displaying your running application.
+
+ ![](images/blockstack-signin.png)
+
+ At this point, the browser is running a Blockstack server on your local host.
+ This is for testing your applications only.
+
+6. Choose **Sign in with Blockstack**
+
+ The system displays a prompt allowing you to create a new Blockstack ID or restore an existing one.
+
+ ![](images/create-restore.png)
+
+7. Follow the prompts appropriate to your situation.
+
+ If you are restoring an existing ID, you may see a prompt about your user
+ being nameless, ignore it. At this point you have only a single application
+ on your test server. So, you should see this single application, with your
+ own `blockstack.id` display name, once you are signed in:
+
+ ![](images/running-app.png)
+
+
+### Add a redirect end point to your application
+
+When a user opens the webapp from the Blockstack browser on an Android phone,
+you want the web app to redirect the user to your Android application. The work
+you do here will allow it.
+
+1. From the terminal command line, change directory to the root of your sample
+application directory.
+
+2. Use the `touch` command to add a redirect endpoint to your application.
+
+ This endpoint on the web version of your app will redirect Android users back
+ to your mobile app.
+
+ ```bash
+ $ touch public/redirect.html
+ ```
+
+3. Open `redirect.html` and add code to the endpoint.
+
+ ```html
+
+
+
+ Hello, Blockstack!
+
+
+
+
+ ```
+
+ Blockstack apps are identified by their domain names. The endpoint will
+ receive a get request with the query parameter `authResponse=XXXX` and
+ should redirect the browser to `myblockstackapp:XXXX`.
+
+ `myblockstackapp:` is custom protocol handler. The handler should be unique
+ to your application. Your app's web-based authentication uses this handler
+ to redirect the user back to your Android app. Later, you'll add a reference
+ to this handler in your Android application.
+
+5. Close and save the `redirect.html` file.
+6. Ensure your Blockstack compiles successfully.
+
+## Create the hello-android project
+
+In this section, you'll create an Android application in Android Studio. You'll
+run the application in the emulator to test it.
+
+### Create a simple project
+
+In this section, you create an inital project. You'll validate the application's
+iniatial state by creating an emulator to run it in. Open Android Studio and do the following:
+
+
+1. Open Android Studio and choose **Start a new Andriod Studio project**.
+
+ If studio is already started, choose **File > New > New Project**.
+
+2. Enter these fields in the **Create Android Project** page.
+
+
+
+3. Press **Next** to display **Target Android Devices**.
+4. Check **Phone and Tablet**.
+5. Choose API 27: Andriod 8.1 (Oreo) for the target version.
+6. Press **Next**.
+7. Choose **Empty Activity** and press **Next**.
+8. Leave the **Configure Activity** dialog with its defaults.
+
+ ![](images/configure-activity.png)
+
+9. Press **Finish**.
+
+ Android studio builds your initial project. This can take a bit the first time you do it.
+
+ ![](images/initial-build.png)
+
+### Run the app in an emulator
+
+In this section, you run the appliation and create an emulator when prompted.
+
+1. Once the project is imported into studio, click the `app` module in the **Project** window.
+
+2. Then, select **Run > Run** (or click the green arrow in the toolbar).
+
+ Studio prompts you to **Select Deployment Target**.
+
+3. Choose **Create New Virtual Device** and press **OK**.
+
+ Studio prompts you to **Select Hardware**.
+
+4. Choose a Phone running Pixel XL.
+
+ ![](images/select-hdw.png)
+
+ Studio prompts you for a system image.
+
+5. Choose **Oreo** which is API level 27 and press **Next**.
+
+ ![](images/oreo-api.png)
+
+ Studio asks you to verify your new emulator configuration.
+
+6. Press **Finish**.
+
+ The emulation takes a moment to build. Then, studio launches the emulation and opens your application.
+
+ ![](images/hello-andriod-1.png)
+
+
+### Configure your application with the Blockstack SDK
+
+Now that you have created your initial project and verified it running in an emulator, you are ready to begin configuring the application for use with Blockstack.
+
+1. In studio, open the `AndroidManifest.xml` file.
+2. Add the a `launchMode` to the `.MainActivity` definition.
+
+ ```XML
+
+ ```
+
+ Blockstack requires that the activity that starts the sign-in process also
+ handles the auth reponse token. This means that the activity needs to run in
+ `singleTask` launch mode.
+
+2. Add an `` with the custom handler for Blockstack.
+
+ ```XML
+
+
+
+
+
+
+ ```
+
+2. Open the Project's `build.gradle` file.
+3. Add the Jitpack repository `maven { url 'https://jitpack.io' }` to the `repositories` section.
+
+ When you finish, that section looks like this:
+
+ ```JS
+ allprojects {
+ repositories {
+ google()
+ jcenter()
+ maven { url 'https://jitpack.io' }
+ }
+ }
+ ```
+
+4. Open the Module `build.gradle` file.
+5. Set the `defaultConfig minSdkVersion` to `19`.
+
+ When you are done, you should see (within your own username not `moxiegirl`):
+
+ ```JS
+ android {
+ compileSdkVersion 27
+ defaultConfig {
+ applicationId "com.example.moxiegirl.hello_android"
+ minSdkVersion 19
+ targetSdkVersion 27
+ versionCode 1
+ versionName "1.0"
+ testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+ }
+ ...
+ }
+ ```
+
+7. Below this, add the Blockstack Android SDK dependency to your project's `dependencies` list:
+
+ When you are done you should see:
+
+ ```JS
+ dependencies {
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+ implementation 'com.android.support:appcompat-v7:27.1.0'
+ implementation 'com.android.support.constraint:constraint-layout:1.1.2'
+ testImplementation 'junit:junit:4.12'
+ androidTestImplementation 'com.android.support.test:runner:1.0.2'
+ androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
+ implementation 'com.github.blockstack:blockstack-android:0.3.0'
+ }
+
+ ```
+
+ **NOTE**: Ignore the warning on the appcompat` dependencies.
+
+8. Sync your project.
+
+ ![](images/sync-project.png)
+
+ Be sure to check the sync completed successfully.
+
+ ![](images/sync-success.png)
+
+10. Run your app in the emulator.
+
+ You've made a lot of changes, make sure the emulator is still running
+ correctly.
+
+### Add a simple interface
+
+1. Open the `app/res/layout/activity_main.xml` file.
+
+ The `activity_main.xml` file defines the graphical elements. Some elements are required before you can functionality to your `MainActivity.kt` code.
+
+3. Replace the entire content of the file with the following code:
+
+ The new interface includes a `BlockstackSignInButton` which is provided by
+ the SDK. This SDK includes a themed "Sign in with Blockstack" button
+ (`BlockstackSignInButton`). You use this button in your here with the
+ `org.blockstack.android.sdk.ui.BlockstackSignInButton` class.
+
+ ```XML
+
+
+
+
+
+
+
+ Apply changes**.
+
+5. Choose **Run > Run app** in the emulator.
+
+ The emulator now contains a new interface with a button:
+
+ ![](images/new-interface.png)
+
+### Add session & authentication code
+
+1. Open the `MainActivity.kt` file.
+2. Add some additional imports to the top below the `android.os.Bundle` import.
+
+ When you are done, your imports should appear as follows:
+
+ ```kotlin
+
+ import android.support.v7.app.AppCompatActivity
+ import android.os.Bundle
+
+ import android.support.v7.app.AppCompatActivity
+ import android.view.View
+ import kotlinx.android.synthetic.main.activity_main.*
+ import org.blockstack.android.sdk.BlockstackSession
+ import org.blockstack.android.sdk.Scope
+ import org.blockstack.android.sdk.UserData
+ import java.net.URI
+ ```
+3. Add a variable for the Blockstack session before `onCreate`.
+
+ ```kotlin
+ class MainActivity : AppCompatActivity() {
+
+ private var _blockstackSession: BlockstackSession? = null
+
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_main)
+ }
+ }
+ ```
+
+4. Replace the existing the `onCreate` function with the following:
+
+ ```kotlin
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_main)
+
+ signInButton.isEnabled = false
+
+ val appDomain = URI("https://flamboyant-darwin-d11c17.netlify.com")
+ val redirectURI = URI("${appDomain}/redirect")
+ val manifestURI = URI("${appDomain}/manifest.json")
+ val scopes = arrayOf(Scope.StoreWrite)
+
+ val config = java.net.URI("https://flamboyant-darwin-d11c17.netlify.com").run {
+ org.blockstack.android.sdk.BlockstackConfig(
+ this,
+ redirectURI,
+ manifestURI,
+ scopes
+ }
+
+ _blockstackSession = BlockstackSession(this, config,
+ onLoadedCallback = {
+ signInButton.isEnabled = true
+ })
+
+
+ signInButton.setOnClickListener { view: View ->
+ blockstackSession().redirectUserToSignIn { userData ->
+ if (userData.hasValue) {
+ runOnUiThread {
+ onSignIn(userData.value!!)
+ }
+ }
+ }
+ }
+ if (intent?.action == Intent.ACTION_VIEW) {
+ // handle the redirect from sign in
+ handleAuthResponse(intent)
+ }
+ }
+ ```
+
+ This new `onCreate` does several things:
+
+ * Define the initial state for the `signInButton`.
+ * Supply authentication information for connecting to your Blockstack app: `appDomain`, `redirectURI`, `manifestURI` and `scopes`
+ * Add a listener for the button click.
+
+ Notice that the application in this example is a URI you have not set up.
+ Registering and application name takes time, so in time's interest you'll
+ use an existing app that is identical to the `hello-world` you created
+ earlier. For a produciton verison, you'll need to replace `appDomain`,
+ `redirectURI`, `manifestURI` and `scopes` with values appropriate for your
+ app.
+
+5. Add a private function to reflect when a user successfully signs in.
+
+ ```kotlin
+ private fun onSignIn(userData: UserData) {
+ userDataTextView.text = "Signed in as ${userData.decentralizedID}"
+
+ signInButton.isEnabled = false
+
+ }
+ ```
+
+6. Handle sign in requests with an `onNewIntent` function if the activity was already opened when signing in
+
+ Retrieve the authentication token from the custom protocol handler call and
+ send it to the Blockstack session.
+
+ ```kotlin
+ override fun onNewIntent(intent: Intent?) {
+ super.onNewIntent(intent)
+
+ if (intent?.action == Intent.ACTION_VIEW) {
+ handleAuthResponse(intent)
+ }
+ }
+ ```
+
+7. Create a handler for the authentication response.
+
+ ```kotlin
+ private fun handleAuthResponse(intent: Intent) {
+ val response = intent.dataString
+ if (response != null) {
+ val authResponseTokens = response.split(':')
+
+ if (authResponseTokens.size > 1) {
+ val authResponse = authResponseTokens[1]
+
+ blockstackSession().handlePendingSignIn(authResponse, { userData ->
+ if (userData.hasValue) {
+ // The user is now signed in!
+ runOnUiThread {
+ onSignIn(userData.value!!)
+ }
+ }
+ })
+ }
+ }
+ }
+ ```
+
+8. Add the convenience method to access the blockstack session.
+
+ ```kotlin
+ fun blockstackSession() : BlockstackSession {
+ val session = _blockstackSession
+ if(session != null) {
+ return session
+ } else {
+ throw IllegalStateException("No session.")
+ }
+ }
+ ```
+
+9. Verify your final `MainActivity.kt` code looks like this:
+
+ ```kotlin
+ class MainActivity : AppCompatActivity() {
+
+ private var _blockstackSession: BlockstackSession? = null
+
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_main)
+
+ signInButton.isEnabled = false
+
+ val appDomain = URI("https://flamboyant-darwin-d11c17.netlify.com")
+ val redirectURI = URI("${appDomain}/redirect")
+ val manifestURI = URI("${appDomain}/manifest.json")
+ val scopes = arrayOf(Scope.StoreWrite)
+
+ _blockstackSession = BlockstackSession(this, appDomain, redirectURI, manifestURI, scopes,
+ onLoadedCallback = {signInButton.isEnabled = true
+ })
+
+
+ signInButton.setOnClickListener { view: View ->
+ blockstackSession().redirectUserToSignIn { userData ->
+ if (userData.hasValue) {
+ runOnUiThread {
+ onSignIn(userData)
+ }
+ }
+ }
+ }
+ if (intent?.action == Intent.ACTION_VIEW) {
+ handleAuthResponse(intent)
+ }
+ }
+
+ private fun onSignIn(userData: UserData) {
+ userDataTextView.text = "Signed in as ${userData.decentralizedID}"
+
+ signInButton.isEnabled = false
+
+ }
+
+ override fun onNewIntent(intent: Intent?) {
+ super.onNewIntent(intent)
+
+ if (intent?.action == Intent.ACTION_VIEW) {
+ handleAuthResponse(intent)
+ }
+ }
+
+ private fun handleAuthResponse(intent: Intent) {
+ val response = intent.dataString
+ if (response != null) {
+ val authResponseTokens = response.split(':')
+
+ if (authResponseTokens.size > 1) {
+ val authResponse = authResponseTokens[1]
+
+ blockstackSession().handlePendingSignIn(authResponse, { userData ->
+ if (userData.hasValue) {
+ // The user is now signed in!
+ runOnUiThread {
+ onSignIn(userData.value!!)
+ }
+ }
+ })
+ }
+ }
+ }
+
+ fun blockstackSession() : BlockstackSession {
+ val session = _blockstackSession
+ if(session != null) {
+ return session
+ } else {
+ throw IllegalStateException("No session.")
+ }
+ }
+
+
+ }
+ ```
+
+### Run the final app in the emulator
+
+1. Choose **Run > Apply changes**.
+2. Choose **Run > Run app** in the emulator.
+3. When you see the application open, choose **Sign in with Blockstack**.
+
+ The system prompts you how to open.
+
+ ![](images/chrome-prompt.png)
+
+4. Choose **Chrome** and click **ALWAYS**.
+5. Move through the rest of the Chrome prompts.
+
+ The system presents you with your final application.
+
+ ![](images/final-app.png)
+
+6. Work through the Blockstack prompts to login.
+
+
+## Where to go next
+
+Congratulations, you've completed your Android app using the new, pre-release
+Blockstack Android SDK. Thank you for trying this pre-release. Please let us
+know about your experience by tweeting to
+[@blockstack](https://twitter.com/blockstack).
+
+Learn more about Blockstack by [trying another tutorial](https://blockstack.org/tutorials).
diff --git a/_android/.svn/pristine/b4/b4b6120a031d86c0b31735cda730ff4fc613167b.svn-base b/_android/.svn/pristine/b4/b4b6120a031d86c0b31735cda730ff4fc613167b.svn-base
new file mode 100644
index 00000000..c3680a2d
Binary files /dev/null and b/_android/.svn/pristine/b4/b4b6120a031d86c0b31735cda730ff4fc613167b.svn-base differ
diff --git a/_android/.svn/pristine/c5/c5cb2871cb79946a062445b18a242ca41c9cb789.svn-base b/_android/.svn/pristine/c5/c5cb2871cb79946a062445b18a242ca41c9cb789.svn-base
new file mode 100644
index 00000000..8dc73142
Binary files /dev/null and b/_android/.svn/pristine/c5/c5cb2871cb79946a062445b18a242ca41c9cb789.svn-base differ
diff --git a/_android/.svn/pristine/e8/e818024be7864ccee3a60629bb6e02c269eb1b86.svn-base b/_android/.svn/pristine/e8/e818024be7864ccee3a60629bb6e02c269eb1b86.svn-base
new file mode 100644
index 00000000..f60822ab
Binary files /dev/null and b/_android/.svn/pristine/e8/e818024be7864ccee3a60629bb6e02c269eb1b86.svn-base differ
diff --git a/_android/.svn/pristine/ec/ec28305cabded3a21d65ddbc0e1aa5fc446567d3.svn-base b/_android/.svn/pristine/ec/ec28305cabded3a21d65ddbc0e1aa5fc446567d3.svn-base
new file mode 100644
index 00000000..fa8b85a3
Binary files /dev/null and b/_android/.svn/pristine/ec/ec28305cabded3a21d65ddbc0e1aa5fc446567d3.svn-base differ
diff --git a/_android/.svn/pristine/f4/f46b7546eae669225bf3d9339962bd87f7a063d0.svn-base b/_android/.svn/pristine/f4/f46b7546eae669225bf3d9339962bd87f7a063d0.svn-base
new file mode 100644
index 00000000..9838c05f
Binary files /dev/null and b/_android/.svn/pristine/f4/f46b7546eae669225bf3d9339962bd87f7a063d0.svn-base differ
diff --git a/_android/.svn/pristine/fb/fb8ec93eaf3886ffae25b002fc76cba129f3b65a.svn-base b/_android/.svn/pristine/fb/fb8ec93eaf3886ffae25b002fc76cba129f3b65a.svn-base
new file mode 100644
index 00000000..01f62b83
Binary files /dev/null and b/_android/.svn/pristine/fb/fb8ec93eaf3886ffae25b002fc76cba129f3b65a.svn-base differ
diff --git a/_android/.svn/wc.db b/_android/.svn/wc.db
new file mode 100644
index 00000000..f32d1b18
Binary files /dev/null and b/_android/.svn/wc.db differ
diff --git a/_android/.svn/wc.db-journal b/_android/.svn/wc.db-journal
new file mode 100644
index 00000000..e69de29b
diff --git a/_android/images/app-flow.png b/_android/images/app-flow.png
new file mode 100644
index 00000000..fa8b85a3
Binary files /dev/null and b/_android/images/app-flow.png differ
diff --git a/_android/images/blockstack-install.png b/_android/images/blockstack-install.png
new file mode 100644
index 00000000..5e4d6256
Binary files /dev/null and b/_android/images/blockstack-install.png differ
diff --git a/_android/images/blockstack-signin.png b/_android/images/blockstack-signin.png
new file mode 100644
index 00000000..081d5050
Binary files /dev/null and b/_android/images/blockstack-signin.png differ
diff --git a/_android/images/chrome-prompt.png b/_android/images/chrome-prompt.png
new file mode 100644
index 00000000..f60822ab
Binary files /dev/null and b/_android/images/chrome-prompt.png differ
diff --git a/_android/images/configure-activity.png b/_android/images/configure-activity.png
new file mode 100644
index 00000000..1be7edf5
Binary files /dev/null and b/_android/images/configure-activity.png differ
diff --git a/_android/images/create-restore.png b/_android/images/create-restore.png
new file mode 100644
index 00000000..914b26e5
Binary files /dev/null and b/_android/images/create-restore.png differ
diff --git a/_android/images/final-app.png b/_android/images/final-app.png
new file mode 100644
index 00000000..01f62b83
Binary files /dev/null and b/_android/images/final-app.png differ
diff --git a/_android/images/hello-andriod-1.png b/_android/images/hello-andriod-1.png
new file mode 100644
index 00000000..c3680a2d
Binary files /dev/null and b/_android/images/hello-andriod-1.png differ
diff --git a/_android/images/helloandroid.zip b/_android/images/helloandroid.zip
new file mode 100644
index 00000000..672ab7e0
Binary files /dev/null and b/_android/images/helloandroid.zip differ
diff --git a/_android/images/initial-build.png b/_android/images/initial-build.png
new file mode 100644
index 00000000..601f3e8a
Binary files /dev/null and b/_android/images/initial-build.png differ
diff --git a/_android/images/new-interface.png b/_android/images/new-interface.png
new file mode 100644
index 00000000..d434f9bb
Binary files /dev/null and b/_android/images/new-interface.png differ
diff --git a/_android/images/oreo-api.png b/_android/images/oreo-api.png
new file mode 100644
index 00000000..1de35691
Binary files /dev/null and b/_android/images/oreo-api.png differ
diff --git a/_android/images/running-app.png b/_android/images/running-app.png
new file mode 100644
index 00000000..9838c05f
Binary files /dev/null and b/_android/images/running-app.png differ
diff --git a/_android/images/select-hdw.png b/_android/images/select-hdw.png
new file mode 100644
index 00000000..2eaccb4f
Binary files /dev/null and b/_android/images/select-hdw.png differ
diff --git a/_android/images/studio-download.png b/_android/images/studio-download.png
new file mode 100644
index 00000000..8dc73142
Binary files /dev/null and b/_android/images/studio-download.png differ
diff --git a/_android/images/sync-project.png b/_android/images/sync-project.png
new file mode 100644
index 00000000..b5e5c141
Binary files /dev/null and b/_android/images/sync-project.png differ
diff --git a/_android/images/sync-success.png b/_android/images/sync-success.png
new file mode 100644
index 00000000..62ae3f5d
Binary files /dev/null and b/_android/images/sync-success.png differ
diff --git a/_android/tutorial.md b/_android/tutorial.md
new file mode 100644
index 00000000..73af907a
--- /dev/null
+++ b/_android/tutorial.md
@@ -0,0 +1,732 @@
+---
+layout: learn
+permalink: /:collection/:path.html
+---
+# Android SDK Tutorial (Pre-release)
+{:.no_toc}
+
+This tutorial is written for readers who are new to either or both Blockstack
+and Android to create a decentralized application. It contains the following
+content:
+
+* TOC
+{:toc}
+
+This tutorial was extensively tested using Android Studio 3.1 on a MacBook Air
+running High Sierra 10.13.4. If your environment is different, you may encounter
+slight or even major discrepancies when performing the procedures in this
+tutorial. Please [join the Blockstack community
+Slack](https://slofile.com/slack/blockstack) and post questions or comments to
+the `#support` channel.
+
+Finally, this tutorial is written for all levels from the beginner to the most
+experienced. For best results, beginners should follow the guide as written. It
+is expected that the fast or furiously brilliant will skip ahead and improvise
+on this material at will. Fair journey one and all.
+
+If you prefer, you can skip working through the tutorial all together. Instead,
+you can [download the final project code](images/helloandroid.zip) and import it
+into Android Studio to review it.
+
+## Understand the sample application flow
+
+When complete, the sample application is a simple `hello-world` display. It is
+intended for user on an Android phone.
+
+![](images/final-app.png)
+
+Only users with an existing `blockstack.id` can run your
+final sample application. When complete, users interact with the sample
+application by doing the following:
+
+![](images/app-flow.png)
+
+## Set up your environment
+
+This sample application has two code bases, a Blockstack `hello-blockstack`
+application and a `hello-andriod` Android application. Before you start
+developing the sample, there are a few elements you need in your environment.
+
+### Install Android Studio
+
+If you are an experienced Android developer and already have an Android
+development environment on your workstation, you can use that and skip this
+step. However, you will need to adjust the remaining instructions for your
+environment.
+
+Follow the installation instructions to download and [Android Studio
+3.1](https://developer.android.com/studio/install) for your operating system.
+Depending on your network connection, this can take between 15-30 minutes.
+
+![](images/studio-download.png)
+
+### Do you have npm?
+
+The Blockstack code in this tutorial relies on the `npm` dependency manager.
+Before you begin, verify you have installed `npm` using the `which` command to
+verify.
+
+```bash
+$ which npm
+/usr/local/bin/npm
+```
+
+If you don't find `npm` in your system, [install
+it](https://www.npmjs.com/get-npm).
+
+### Install the Blockstack test rig
+
+Users interact with Blockstack-enabled applications through a web browser. You
+can Blockstack in test mode, on `localhost` or you can interact with completed
+apps through the Blockstack webapp which is available at
+[https://browser.blockstack.org/].
+
+If you have already installed Blockstack for testing locally and have an
+existing Blockstack ID, skip this section. Otherwise, continue onto install
+Blockstack.
+
+1. Go to [Blockstack](https://blockstack.org/install)
+
+ ![](images/blockstack-install.png)
+
+2. Install the version appropriate for your operating system.
+
+
+### Use npm to install Yeoman and the Blockstack App Generator
+
+You use `npm` to install Yeoman. Yeoman is a generic scaffolding system that
+helps users rapidly start new projects and streamline the maintenance of
+existing projects.
+
+
+1. Install Yeoman.
+
+ ```bash
+ npm install -g yo
+ ```
+2. Install the Blockstack application generator.
+
+ ```bash
+ npm install -g generator-blockstack
+ ```
+
+
+## Build the Blockstack hello-world
+
+In this section, you build a Blockstack `hello-world` application. Then, you
+modify the `hello-world` to interact with the Android app via a redirect.
+
+### Generate and launch your hello-blockstack application
+
+In this section, you build an initial React.js application called
+`hello-blockstack`.
+
+1. Create a `hello-blockstack` directory.
+
+ ```bash
+ mkdir hello-blockstack
+ ```
+
+2. Change into your new directory.
+
+ ```bash
+ cd hello-blockstack
+ ```
+
+3. Use Yeoman and the Blockstack application generator to create your initial `hello-blockstack` application.
+
+ ```bash
+ yo blockstack:react
+ ```
+
+ You should see several interactive prompts.
+
+ ```bash
+ $ yo blockstack:react
+ ==========================================================================
+ We are constantly looking for ways to make yo better!
+ May we anonymously report usage statistics to improve the tool over time?
+ More info: https://github.com/yeoman/insight & http://yeoman.io
+ ========================================================================== No
+
+ _-----_ ╭──────────────────────────╮
+ | | │ Welcome to the │
+ |--(o)--| │ Blockstack app │
+ --------- │ generator! │
+ ( _U_ ) ╰──────────────────────────╯
+ /___A___\ /
+ | ~ |
+ __'.___.'__
+ |° Y
+
+ ? Are you ready to build a Blockstack app in React? (Y/n)
+ ```
+
+4. Respond to the prompts to populate the initial app.
+
+ After the process completes successfully, you see a prompt similar to the following:
+
+ ```bash
+ [fsevents] Success:
+ "/Users/theuser/repos/hello-blockstack/node_modules/fsevents/lib/binding/Release/node-v59-darwin-x64/fse.node"
+ is installed via remote npm notice created a lockfile as package-lock.json.
+ You should commit this file. added 1060 packages in 26.901s
+ ```
+
+5. Run the initial application.
+
+ ```bash
+ $ npm start
+
+ > hello-blockstack@0.0.0 start /Users/moxiegirl/repos/hello-blockstack
+ > webpack-dev-server
+
+ Project is running at http://localhost:8080/
+ webpack output is served from /
+ 404s will fallback to /index.html
+ Hash: 4d2312ba236a4b95dc3a
+ Version: webpack 2.7.0
+ Time: 2969ms
+ Asset Size Chunks Chunk Names
+ ....
+ Child html-webpack-plugin for "index.html":
+ chunk {0} index.html 541 kB [entry] [rendered]
+ [0] ./~/lodash/lodash.js 540 kB {0} [built]
+ [1] ./~/html-webpack-plugin/lib/loader.js!./src/index.html 533 bytes {0} [built]
+ [2] (webpack)/buildin/global.js 509 bytes {0} [built]
+ [3] (webpack)/buildin/module.js 517 bytes {0} [built]
+ webpack: Compiled successfully.
+ ```
+
+ The system opens a browser displaying your running application.
+
+ ![](images/blockstack-signin.png)
+
+ At this point, the browser is running a Blockstack server on your local host.
+ This is for testing your applications only.
+
+6. Choose **Sign in with Blockstack**
+
+ The system displays a prompt allowing you to create a new Blockstack ID or restore an existing one.
+
+ ![](images/create-restore.png)
+
+7. Follow the prompts appropriate to your situation.
+
+ If you are restoring an existing ID, you may see a prompt about your user
+ being nameless, ignore it. At this point you have only a single application
+ on your test server. So, you should see this single application, with your
+ own `blockstack.id` display name, once you are signed in:
+
+ ![](images/running-app.png)
+
+
+### Add a redirect end point to your application
+
+When a user opens the webapp from the Blockstack browser on an Android phone,
+you want the web app to redirect the user to your Android application. The work
+you do here will allow it.
+
+1. From the terminal command line, change directory to the root of your sample
+application directory.
+
+2. Use the `touch` command to add a redirect endpoint to your application.
+
+ This endpoint on the web version of your app will redirect Android users back
+ to your mobile app.
+
+ ```bash
+ $ touch public/redirect.html
+ ```
+
+3. Open `redirect.html` and add code to the endpoint.
+
+ ```html
+
+
+
+ Hello, Blockstack!
+
+
+
+
+ ```
+
+ Blockstack apps are identified by their domain names. The endpoint will
+ receive a get request with the query parameter `authResponse=XXXX` and
+ should redirect the browser to `myblockstackapp:XXXX`.
+
+ `myblockstackapp:` is custom protocol handler. The handler should be unique
+ to your application. Your app's web-based authentication uses this handler
+ to redirect the user back to your Android app. Later, you'll add a reference
+ to this handler in your Android application.
+
+5. Close and save the `redirect.html` file.
+6. Ensure your Blockstack compiles successfully.
+
+## Create the hello-android project
+
+In this section, you'll create an Android application in Android Studio. You'll
+run the application in the emulator to test it.
+
+### Create a simple project
+
+In this section, you create an inital project. You'll validate the application's
+iniatial state by creating an emulator to run it in. Open Android Studio and do the following:
+
+
+1. Open Android Studio and choose **Start a new Andriod Studio project**.
+
+ If studio is already started, choose **File > New > New Project**.
+
+2. Enter these fields in the **Create Android Project** page.
+
+
+
+3. Press **Next** to display **Target Android Devices**.
+4. Check **Phone and Tablet**.
+5. Choose API 27: Andriod 8.1 (Oreo) for the target version.
+6. Press **Next**.
+7. Choose **Empty Activity** and press **Next**.
+8. Leave the **Configure Activity** dialog with its defaults.
+
+ ![](images/configure-activity.png)
+
+9. Press **Finish**.
+
+ Android studio builds your initial project. This can take a bit the first time you do it.
+
+ ![](images/initial-build.png)
+
+### Run the app in an emulator
+
+In this section, you run the appliation and create an emulator when prompted.
+
+1. Once the project is imported into studio, click the `app` module in the **Project** window.
+
+2. Then, select **Run > Run** (or click the green arrow in the toolbar).
+
+ Studio prompts you to **Select Deployment Target**.
+
+3. Choose **Create New Virtual Device** and press **OK**.
+
+ Studio prompts you to **Select Hardware**.
+
+4. Choose a Phone running Pixel XL.
+
+ ![](images/select-hdw.png)
+
+ Studio prompts you for a system image.
+
+5. Choose **Oreo** which is API level 27 and press **Next**.
+
+ ![](images/oreo-api.png)
+
+ Studio asks you to verify your new emulator configuration.
+
+6. Press **Finish**.
+
+ The emulation takes a moment to build. Then, studio launches the emulation and opens your application.
+
+ ![](images/hello-andriod-1.png)
+
+
+### Configure your application with the Blockstack SDK
+
+Now that you have created your initial project and verified it running in an emulator, you are ready to begin configuring the application for use with Blockstack.
+
+1. In studio, open the `AndroidManifest.xml` file.
+
+2. Add an `` with the custom handler for Blockstack.
+
+ ```XML
+
+
+
+
+
+
+ ```
+
+2. Open the Project's `build.gradle` file.
+3. Add the Jitpack repository `maven { url 'https://jitpack.io' }` to the `repositories` section.
+
+ When you finish, that section looks like this:
+
+ ```JS
+ allprojects {
+ repositories {
+ google()
+ jcenter()
+ maven { url 'https://jitpack.io' }
+ }
+ }
+ ```
+
+4. Open the Module `build.gradle` file.
+5. Set the `defaultConfig minSdkVersion` to `19`.
+
+ When you are done, you should see (within your own username not `moxiegirl`):
+
+ ```JS
+ android {
+ compileSdkVersion 27
+ defaultConfig {
+ applicationId "com.example.moxiegirl.hello_android"
+ minSdkVersion 19
+ targetSdkVersion 27
+ versionCode 1
+ versionName "1.0"
+ testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+ }
+ ...
+ }
+ ```
+
+7. Below this, add the Blockstack Android SDK dependency to your project's `dependencies` list:
+
+ When you are done you should see:
+
+ ```JS
+ dependencies {
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+ implementation 'com.android.support:appcompat-v7:27.1.1'
+ implementation 'com.android.support.constraint:constraint-layout:1.1.3'
+ implementation 'com.android.support:design:27.1.1'
+ testImplementation 'junit:junit:4.12'
+ androidTestImplementation 'com.android.support.test:runner:1.0.2'
+ androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
+ implementation 'com.github.blockstack:blockstack-android:0.4.0'
+ }
+
+ ```
+
+ **NOTE**: Ignore the warning on the appcompat` dependencies.
+
+8. Sync your project.
+
+ ![](images/sync-project.png)
+
+ Be sure to check the sync completed successfully.
+
+ ![](images/sync-success.png)
+
+10. Run your app in the emulator.
+
+ You've made a lot of changes, make sure the emulator is still running
+ correctly.
+
+### Add a simple interface
+
+1. Open the `app/res/layout/activity_main.xml` file.
+
+ The `activity_main.xml` file defines the graphical elements. Some elements are required before you can functionality to your `MainActivity.kt` code.
+
+3. Replace the entire content of the file with the following code:
+
+ The new interface includes a `BlockstackSignInButton` which is provided by
+ the SDK. This SDK includes a themed "Sign in with Blockstack" button
+ (`BlockstackSignInButton`). You use this button here with the
+ `org.blockstack.android.sdk.ui.BlockstackSignInButton` class.
+
+ ```XML
+
+
+
+
+
+
+
+
+ ```
+
+ This codes adds a button and some text to your application.
+
+4. Choose **Run > Apply changes**.
+
+5. Choose **Run > Run app** in the emulator.
+
+ The emulator now contains a new interface with a button:
+
+ ![](images/new-interface.png)
+
+### Add session & authentication code
+
+1. Open the `MainActivity.kt` file.
+2. Add some additional imports to the top below the `android.os.Bundle` import.
+
+ When you are done, your imports should appear as follows:
+
+ ```kotlin
+ import android.content.Intent
+ import android.os.Bundle
+ import android.support.v7.app.AppCompatActivity
+ import android.view.View
+ import kotlinx.android.synthetic.main.activity_main.*
+ import org.blockstack.android.sdk.BlockstackSession
+ import org.blockstack.android.sdk.Scope
+ import org.blockstack.android.sdk.UserData
+ import org.blockstack.android.sdk.toBlockstackConfig
+ ```
+3. Add a variable for the Blockstack session before `onCreate`.
+
+ ```kotlin
+ class MainActivity : AppCompatActivity() {
+
+ private var _blockstackSession: BlockstackSession? = null
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_main)
+ }
+ }
+ ```
+
+4. Replace the existing the `onCreate` function with the following:
+
+ ```kotlin
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_main)
+
+ val scopes = arrayOf(Scope.StoreWrite)
+ val config = "https://flamboyant-darwin-d11c17.netlify.com"
+ .toBlockstackConfig(scopes)
+
+ _blockstackSession = BlockstackSession(this, config)
+
+ signInButton.isEnabled = true
+
+ signInButton.setOnClickListener { view: View ->
+ blockstackSession().redirectUserToSignIn {
+ // only called on error
+ }
+ }
+ if (intent?.action == Intent.ACTION_VIEW) {
+ // handle the redirect from sign in
+ handleAuthResponse(intent)
+ }
+ }
+ ```
+
+ This new `onCreate` does several things:
+
+ * Define the initial state for the `signInButton`.
+ * Supply authentication information for connecting to your Blockstack app: `appDomain` and `scopes` (for `redirectURI`, `manifestURI` the default values are used)
+ * Add a listener for the button click.
+
+ Notice that the application in this example is a URI you have not set up.
+ Registering and application name takes time, so in time's interest you'll
+ use an existing app that is identical to the `hello-world` you created
+ earlier. For a production version, you'll need to replace `appDomain`,
+ `redirectURI`, `manifestURI` and `scopes` with values appropriate for your
+ app.
+
+5. Add a private function to reflect when a user successfully signs in.
+
+ ```kotlin
+ private fun onSignIn(userData: UserData) {
+ userDataTextView.text = "Signed in as ${userData.decentralizedID}"
+ signInButton.isEnabled = false
+ }
+ ```
+
+6. Handle sign in requests with an `onNewIntent` function if the activity was already opened when signing in
+
+ Retrieve the authentication token from the custom protocol handler call and
+ send it to the Blockstack session.
+
+ ```kotlin
+ override fun onNewIntent(intent: Intent?) {
+ super.onNewIntent(intent)
+
+ if (intent?.action == Intent.ACTION_VIEW) {
+ handleAuthResponse(intent)
+ }
+ }
+ ```
+
+7. Create a handler for the authentication response.
+
+ ```kotlin
+ private fun handleAuthResponse(intent: Intent) {
+ val response = intent.dataString
+ if (response != null) {
+ val authResponseTokens = response.split(':')
+
+ if (authResponseTokens.size > 1) {
+ val authResponse = authResponseTokens[1]
+
+ blockstackSession().handlePendingSignIn(authResponse, { userData ->
+ if (userData.hasValue) {
+ // The user is now signed in!
+ runOnUiThread {
+ onSignIn(userData.value!!)
+ }
+ }
+ })
+ }
+ }
+ }
+ ```
+
+8. Add the convenience method to access the blockstack session.
+
+ ```kotlin
+ fun blockstackSession() : BlockstackSession {
+ val session = _blockstackSession
+ if(session != null) {
+ return session
+ } else {
+ throw IllegalStateException("No session.")
+ }
+ }
+ ```
+
+9. Verify your final `MainActivity.kt` code looks like this:
+
+ ```kotlin
+ class MainActivity : AppCompatActivity() {
+
+ private var _blockstackSession: BlockstackSession? = null
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_main)
+
+ signInButton.isEnabled = false
+
+ val scopes = arrayOf(Scope.StoreWrite)
+ val config = "https://flamboyant-darwin-d11c17.netlify.com"
+ .toBlockstackConfig(scopes)
+
+ _blockstackSession = BlockstackSession(this, config)
+ signInButton.isEnabled = true
+
+ signInButton.setOnClickListener { view: View ->
+ blockstackSession().redirectUserToSignIn {
+ // only called on error
+ }
+ }
+ if (intent?.action == Intent.ACTION_VIEW) {
+ handleAuthResponse(intent)
+ }
+ }
+
+ private fun onSignIn(userData: UserData) {
+ userDataTextView.text = "Signed in as ${userData.decentralizedID}"
+
+ signInButton.isEnabled = false
+ }
+
+ override fun onNewIntent(intent: Intent?) {
+ super.onNewIntent(intent)
+
+ if (intent?.action == Intent.ACTION_VIEW) {
+ handleAuthResponse(intent)
+ }
+ }
+
+ private fun handleAuthResponse(intent: Intent) {
+ val response = intent.dataString
+ if (response != null) {
+ val authResponseTokens = response.split(':')
+
+ if (authResponseTokens.size > 1) {
+ val authResponse = authResponseTokens[1]
+
+ blockstackSession().handlePendingSignIn(authResponse, { userData ->
+ if (userData.hasValue) {
+ // The user is now signed in!
+ runOnUiThread {
+ onSignIn(userData.value!!)
+ }
+ }
+ })
+ }
+ }
+ }
+
+ fun blockstackSession() : BlockstackSession {
+ val session = _blockstackSession
+ if(session != null) {
+ return session
+ } else {
+ throw IllegalStateException("No session.")
+ }
+ }
+ }
+ ```
+
+### Run the final app in the emulator
+
+1. Choose **Run > Apply changes**.
+2. Choose **Run > Run app** in the emulator.
+3. When you see the application open, choose **Sign in with Blockstack**.
+
+ The system prompts you how to open.
+
+ ![](images/chrome-prompt.png)
+
+4. Choose **Chrome** and click **ALWAYS**.
+5. Move through the rest of the Chrome prompts.
+
+ The system presents you with your final application.
+
+ ![](images/final-app.png)
+
+6. Work through the Blockstack prompts to login.
+
+
+## Where to go next
+
+Congratulations, you've completed your Android app using the new, pre-release
+Blockstack Android SDK. Thank you for trying this pre-release. Please let us
+know about your experience by tweeting to
+[@blockstack](https://twitter.com/blockstack).
+
+Learn more about Blockstack by [trying another tutorial](https://blockstack.org/tutorials).
diff --git a/_browser/.svn/entries b/_browser/.svn/entries
new file mode 100644
index 00000000..48082f72
--- /dev/null
+++ b/_browser/.svn/entries
@@ -0,0 +1 @@
+12
diff --git a/_browser/.svn/format b/_browser/.svn/format
new file mode 100644
index 00000000..48082f72
--- /dev/null
+++ b/_browser/.svn/format
@@ -0,0 +1 @@
+12
diff --git a/_browser/.svn/pristine/04/04f3a32b0bc311047a20e12c72428e50812cdbd9.svn-base b/_browser/.svn/pristine/04/04f3a32b0bc311047a20e12c72428e50812cdbd9.svn-base
new file mode 100644
index 00000000..829f7c1f
Binary files /dev/null and b/_browser/.svn/pristine/04/04f3a32b0bc311047a20e12c72428e50812cdbd9.svn-base differ
diff --git a/_browser/.svn/pristine/07/0760488b80dc376bd96b4dd0ec94f4e79292cf9b.svn-base b/_browser/.svn/pristine/07/0760488b80dc376bd96b4dd0ec94f4e79292cf9b.svn-base
new file mode 100644
index 00000000..36684bff
--- /dev/null
+++ b/_browser/.svn/pristine/07/0760488b80dc376bd96b4dd0ec94f4e79292cf9b.svn-base
@@ -0,0 +1,330 @@
+---
+layout: learn
+permalink: /:collection/:path.html
+---
+# Hello, Blockstack Tutorial
+
+In this tutorial, you generate a simple application on Blockstack. The application
+is a single-page application (SPA) that runs completely client-side. The
+application has no backend API to talk to, other than the identity and storage
+API that the user provides. In this sense, the application is a completely
+decentralized, server-less application. You work through the following sections:
+
+* TOC
+{:toc}
+
+## About this tutorial and the prerequisites you need
+
+For this tutorial, we will use the following tools:
+
+- `npm` to manage dependencies and scripts
+- `browserify` to compile node code into browser-ready code
+- `blockstack.js` to authenticate the user and work with the user's identity/profile information
+
+At minimum, Blockstack requires macOS High Sierra. This tutorial was written for
+a user running macOS High Sierra 10.13.4. The application you build is a
+React.js application that is completely decentralized and server-less. While
+not strictly required to follow along, basic familiarity with React.js is
+helpful.
+
+When complete, the app is capable of the following:
+
+- authenticating users using Blockstack
+- posting new statuses
+- displaying statuses in the user profile
+- looking up the profiles and statuses of other users
+
+The basic identity and storage services are provided by `blockstack.js`. To test
+the application, you need to have already registered a Blockstack ID.
+
+The tutorial relies on the `npm` dependency manager. Before you begin, verify
+you have installed `npm` using the `which` command to verify.
+
+```bash
+$ which npm
+/usr/local/bin/npm
+```
+
+If you don't find `npm` in your system, [install
+it](https://www.npmjs.com/get-npm).
+
+Finally, make sure you have [created at least one Blockstack ID]({{ site.baseurl }}/browser/ids-introduction.html#create-an-initial-blockstack-id). You'll use this ID to interat with the application.
+
+## Use npm to install Yeoman and the Blockstack App Generator
+
+You use `npm` to install Yeoman. Yeoman is a generic scaffolding system that
+helps users rapidly start new projects and streamline the maintenance of
+existing projects.
+
+
+1. Install Yeoman.
+
+ ```bash
+ npm install -g yo
+ ```
+2. Install the Blockstack application generator.
+
+ ```bash
+ npm install -g generator-blockstack
+ ```
+
+## Generate an initial Blockstack application
+
+In this section, you build an initial React.js application called `hello-world-tutorial`.
+
+1. Create the `hello-world-tutorial` directory.
+
+ ```bash
+ mkdir hello-world-tutorial
+ ```
+
+2. Change into your new directory.
+
+ ```bash
+ cd hello-world-tutorial
+ ```
+
+3. Use Yeoman and the Blockstack application generator to create your initial `hello-world-tutorial` application.
+
+ ```bash
+ yo blockstack
+ ```
+
+ You should see several interactive prompts.
+
+ ```bash
+ $ yo blockstack
+
+ _-----_ ╭──────────────────────────╮
+ | | │ Welcome to the │
+ |--(o)--| │ Blockstack app │
+ `---------´ │ generator! │
+ ( _´U`_ ) ╰──────────────────────────╯
+ /___A___\ /
+ | ~ |
+ __'.___.'__
+ ´ ` |° ´ Y `
+
+ ? Are you ready to build a Blockstack app in React? (Y/n)
+ ```
+
+4. Respond to the prompts to populate the initial app.
+
+ After the process completes successfully, you see a prompt similar to the following:
+
+ ```bash
+ ...
+ create public/icon-192x192.png
+ create public/index.html
+ create public/robots.txt
+ create public/manifest.json
+
+
+ I'm all done. Running npm install for you to install the required dependencies. If this fails, try running the command yourself.
+ ```
+
+Depending on your environment you may have some problems with the `npm` packages. Go ahead and fix these before continuing to the next section.
+
+## Review the basic application structure
+
+The initial application you create is a generic Javascript application you run
+with a local express node. Before you continue, take a moment to examine the
+structure of this generic application structure:
+
+| File | Description |
+|------------------|-----------------------------------|
+| .editorconfig | Sets universal values for editor. |
+| .gitignore | Git configuration file. |
+| firebase.json | Configuragion for mobile application.|
+| package.json | Specifies required packages. |
+| requires.js | A Javascript module loader. |
+| server.js | Simple static server configuration.|
+
+In the `public` folder you find these files:
+
+| File | Description |
+|------------------|-----------------------------------|
+| app.css | Contains application styles. |
+| app.js | Main application file. |
+| boostrap.min.css | Minifield css for production. |
+| icon-192x192.png | Application icon |
+| index.html | Single page. |
+| manifest.json | Tells the browser about the application and how it should behave.|
+| robots.txt | Configures crawling and indexing. |
+
+The simple static file server in the `server.js`file serves all of the files in
+the `/public` directory, including `index.html`, `app.js`, `bootstrap.min.css`
+and `app.css`. The main file of the application is in the `app.js`. It contains
+the majority of the application logic.
+
+## Start the server and view the application
+
+When you start the server, it will create a Node.js server, start it locally,
+and open your browser 'http://localhost:5000'. From the root of your new application directory:
+
+1. Start the application server.
+
+ ```bash
+ npm start
+ ```
+
+ The first time you run it, your system prompts you to accept incoming connections.
+
+ ![Network Connection](images/network-connections.gif)
+
+2. Choose **Allow**.
+
+3. Open your browser to `http://localhost:8080`.
+
+ You should see a simple application:
+
+ ![](images/initial-app.gif)
+
+4. Choose **Sign In with Blockstack**.
+
+ The application detects whether the user has the Blockstack client edition installed or
+ not. This is done automatically by the Blockstack API, more about this later.
+ What the browser displays depends on the users' current state.
+
+ | Using web app | Has client edition installed |
+ |------------------|-----------------------------------|
+ | ![](images/login-choice.png) | ![](images/login.gif) |
+
+ If the user logged into the Blockstack Browser but not reset it, the user can
+ simply use the exiting identity.
+
+ ![](images/login-no-auth.png)
+
+ If the user chooses **Deny**, the Blockstack Browser displays its
+ **Home** page but the user is not logged into the sample application.
+
+5. Leave your new application running and move onto the next section.
+
+## Understand the generated application code
+
+In this section, you look at the basic application generated with the `yo
+blockstack` command. The generated code contains simple authentication methods
+that allow a user to log into the browser. The main application code is located
+in the `public/app.css` file. Open this file now.
+
+All of the code in the file is wrapped in an event
+listener.
+
+```js
+document.addEventListener("DOMContentLoaded", function(event) {
+})
+```
+
+This listener that waits until the DOM content is loaded. Then, it creates an auth request and redirects the user to sign in:
+
+```js
+document.getElementById('signin-button').addEventListener('click', function() {
+ blockstack.redirectUserToSignIn()
+})
+```
+
+You can find the `redirectUserToSignIn()` function is part of the [Blockstack Javascript documentation](https://blockstack.github.io/blockstack.js/). There is also a sign out button handler. This handler deletes the local user data and signs the user out:
+
+```js
+document.getElementById('signout-button').addEventListener('click', function() {
+ blockstack.signUserOut(window.location.origin)
+})
+```
+
+The handlers are followed by a `showProfile()` function for showing the user's profile:
+
+```js
+function showProfile(profile) {
+ var person = new blockstack.Person(profile)
+ document.getElementById('heading-name').innerHTML = person.name() ? person.name() : "Nameless Person"
+ if(person.avatarUrl()) {
+ document.getElementById('avatar-image').setAttribute('src', person.avatarUrl())
+ }
+ document.getElementById('section-1').style.display = 'none'
+ document.getElementById('section-2').style.display = 'block'
+}
+```
+
+Each `getElementById()` function refers to elemments in the `index.html` file.
+
+Once a user is successfully signed in, there is logic for loading the user
+profile and displaying the application. As illustrated earlier, there are
+several states the user can be in:
+
+- The user is already signed in
+- The user has a pending sign in request
+- The user is signed out
+
+The application handles these situtations as followed:
+
+```js
+if (blockstack.isUserSignedIn()) {
+ var profile = blockstack.loadUserData().profile
+ showProfile(profile)
+} else if (blockstack.isSignInPending()) {
+ blockstack.handlePendingSignIn().then(function(userData) {
+ window.location = window.location.origin
+ })
+}
+```
+
+When the user is signed in, Blockstack loads the user data from local storage
+and displays the profile with the `showProfile()` function. When the user has a
+pending sign in request, the appplication signs the user in and redirects the
+user back to the home page.
+
+### Application manifest
+
+The application's `/public/manifest.json` file configures your app. The
+configurations dictate how the application is displayed in auth views and on
+user home screens. The contents are very simple:
+
+```json
+{
+ "name": "Hello, Blockstack",
+ "start_url": "localhost:5000",
+ "description": "A simple demo of Blockstack Auth",
+ "icons": [{
+ "src": "https://helloblockstack.com/icon-192x192.png",
+ "sizes": "192x192",
+ "type": "image/png"
+ }]
+}
+```
+
+Keep it as is or fill it in with new information that describes your app.
+
+### Save your application code
+
+Complete the tutorial by storing your app code on GitHub. Before you begin, make sure you have a GitHub account and have configured your environment to use it.
+
+1. Initialize the application code as a Git repo.
+
+ ```bash
+ git init
+ ```
+
+2. Add and commit all of the files:
+
+ ```bash
+ git add . && git commit -m "first commit"
+ ```
+
+3. In GitHub, create a `hello-blockstack` repository.
+
+4. Back in your termininal window, add a remote for GitHub.
+
+ Make sure to fill in your username:
+
+ ```bash
+ git remote add origin git@github.com:YOUR_USERNAME_HERE/hello-blockstack.git
+ ```
+
+5. Push your new code to the master branch of the remote repo:
+
+ ```
+ git push origin master
+ ```
+
+You're done! You just built your first Blockstack app and shipped the code.
+You're well on your way to becoming a Blockstack app legend.
diff --git a/_browser/.svn/pristine/08/085c1a3260d4d04fcd82252787ba093d06446210.svn-base b/_browser/.svn/pristine/08/085c1a3260d4d04fcd82252787ba093d06446210.svn-base
new file mode 100644
index 00000000..bf6c096a
Binary files /dev/null and b/_browser/.svn/pristine/08/085c1a3260d4d04fcd82252787ba093d06446210.svn-base differ
diff --git a/_browser/.svn/pristine/12/1284f902d27c0fdb01787c315fa61ee525538d65.svn-base b/_browser/.svn/pristine/12/1284f902d27c0fdb01787c315fa61ee525538d65.svn-base
new file mode 100644
index 00000000..5352b913
Binary files /dev/null and b/_browser/.svn/pristine/12/1284f902d27c0fdb01787c315fa61ee525538d65.svn-base differ
diff --git a/_browser/.svn/pristine/28/28885ce546124804666f1c735f1fb916582a1a98.svn-base b/_browser/.svn/pristine/28/28885ce546124804666f1c735f1fb916582a1a98.svn-base
new file mode 100644
index 00000000..9fef9de2
Binary files /dev/null and b/_browser/.svn/pristine/28/28885ce546124804666f1c735f1fb916582a1a98.svn-base differ
diff --git a/_browser/.svn/pristine/2c/2cb66479d94646ba1c3c651f26dbd9683e929114.svn-base b/_browser/.svn/pristine/2c/2cb66479d94646ba1c3c651f26dbd9683e929114.svn-base
new file mode 100644
index 00000000..006eeca5
Binary files /dev/null and b/_browser/.svn/pristine/2c/2cb66479d94646ba1c3c651f26dbd9683e929114.svn-base differ
diff --git a/_browser/.svn/pristine/2e/2e837afccc4a402a90dc0b7e580109e49e3252e2.svn-base b/_browser/.svn/pristine/2e/2e837afccc4a402a90dc0b7e580109e49e3252e2.svn-base
new file mode 100644
index 00000000..a5f0c27f
Binary files /dev/null and b/_browser/.svn/pristine/2e/2e837afccc4a402a90dc0b7e580109e49e3252e2.svn-base differ
diff --git a/_browser/.svn/pristine/2f/2f00af279deecacd5b47bdc32a0106e23b2a2f64.svn-base b/_browser/.svn/pristine/2f/2f00af279deecacd5b47bdc32a0106e23b2a2f64.svn-base
new file mode 100644
index 00000000..019c67db
Binary files /dev/null and b/_browser/.svn/pristine/2f/2f00af279deecacd5b47bdc32a0106e23b2a2f64.svn-base differ
diff --git a/_browser/.svn/pristine/30/30473db14d0ed5ac772c32ab2e89375faa2b0133.svn-base b/_browser/.svn/pristine/30/30473db14d0ed5ac772c32ab2e89375faa2b0133.svn-base
new file mode 100644
index 00000000..c2626b50
Binary files /dev/null and b/_browser/.svn/pristine/30/30473db14d0ed5ac772c32ab2e89375faa2b0133.svn-base differ
diff --git a/_browser/.svn/pristine/30/30e89a5d274e5137e687939f31ca471aea7462a3.svn-base b/_browser/.svn/pristine/30/30e89a5d274e5137e687939f31ca471aea7462a3.svn-base
new file mode 100644
index 00000000..787392e1
--- /dev/null
+++ b/_browser/.svn/pristine/30/30e89a5d274e5137e687939f31ca471aea7462a3.svn-base
@@ -0,0 +1,27 @@
+# Tutorials
+
+**Note: This data is being digested by blockstack.org. Do not change the formatting of this list unless you first make an adjustment to the code on blockstack.org.**
+
+### Multi-player Storage
+
+- urlSlug: multi-player-storage
+- image: /images/tutorials/multi-player-storage.png
+- description: Build a decentralized micro-blogging app using multi-player Gaia storage.
+
+### Managing Data with Gaia
+
+- urlSlug: managing-data-with-gaia
+- image: /images/tutorials/managing-data-with-gaia.png
+- description: This series will focus on teaching you to think like a Blockstack developer working with Gaia.
+
+### Blockstack Todo
+
+- urlSlug: todo-list
+- image: /images/tutorials/todo-list.png
+- description: Walk through creating a basic Todo application with Blockstack. Learn about Sign In flow and Gaia storage.
+
+### Hello Blockstack
+
+- urlSlug: hello-blockstack
+- image: /images/tutorials/hello-blockstack.jpg
+- description: Build a simple single-page JavaScript application that runs completely client-side without any servers.
diff --git a/_browser/.svn/pristine/33/33f4fbc3c99fe5df9c5eb23cc4aaf25165722419.svn-base b/_browser/.svn/pristine/33/33f4fbc3c99fe5df9c5eb23cc4aaf25165722419.svn-base
new file mode 100644
index 00000000..433ef3d5
Binary files /dev/null and b/_browser/.svn/pristine/33/33f4fbc3c99fe5df9c5eb23cc4aaf25165722419.svn-base differ
diff --git a/_browser/.svn/pristine/37/373b7d67a3d5c2de4723fcd45470854cf0c5ca6e.svn-base b/_browser/.svn/pristine/37/373b7d67a3d5c2de4723fcd45470854cf0c5ca6e.svn-base
new file mode 100644
index 00000000..26d88672
Binary files /dev/null and b/_browser/.svn/pristine/37/373b7d67a3d5c2de4723fcd45470854cf0c5ca6e.svn-base differ
diff --git a/_browser/.svn/pristine/3f/3f89163556affc6e77a6630136bf6897bc9ae8f6.svn-base b/_browser/.svn/pristine/3f/3f89163556affc6e77a6630136bf6897bc9ae8f6.svn-base
new file mode 100644
index 00000000..1d95fee1
Binary files /dev/null and b/_browser/.svn/pristine/3f/3f89163556affc6e77a6630136bf6897bc9ae8f6.svn-base differ
diff --git a/_browser/.svn/pristine/42/423c91a747d0f3570fb0d63199c9adcbe6baef1d.svn-base b/_browser/.svn/pristine/42/423c91a747d0f3570fb0d63199c9adcbe6baef1d.svn-base
new file mode 100644
index 00000000..d2c2dda2
Binary files /dev/null and b/_browser/.svn/pristine/42/423c91a747d0f3570fb0d63199c9adcbe6baef1d.svn-base differ
diff --git a/_browser/.svn/pristine/49/49a137f4f026b72e9ba4af3fd546fe8baff34c09.svn-base b/_browser/.svn/pristine/49/49a137f4f026b72e9ba4af3fd546fe8baff34c09.svn-base
new file mode 100644
index 00000000..75c17f14
--- /dev/null
+++ b/_browser/.svn/pristine/49/49a137f4f026b72e9ba4af3fd546fe8baff34c09.svn-base
@@ -0,0 +1,328 @@
+---
+title: Tour of a Blockstack application
+description: Walk through creating a basic Todo application with Blockstack. Learn about Sign In flow and Gaia storage.
+image: /images/article-photos/chalkboard.jpg
+youtube: https://www.youtube.com/embed/oyvg-h0obFw
+---
+
+In this tutorial, you build the code for and run a single-page application (SPA)
+with Blockstack and Vue.js. Once the application is running, you take a tour
+through the applications' Blockstack functionality. You'll learn how it manages
+authentiation using a Blockstack ID and how it stores information associated
+with that ID using Blockstack Storage (Gaia).
+
+## Prerequisites
+
+Make sure you have [created at least one Blockstack ID](ids-introduction#create-an-initial-blockstack-id). You'll use this ID to Finteract with the Todo application.
+
+The applicaton code relies on both the `npm` and the `yarn` package managers.
+Before you begin, verify you have these tools `npm` using the `which` command to
+verify.
+
+```bash
+$ which npm
+/usr/local/bin/npm
+$ which yarn
+/usr/local/bin/yarn
+```
+
+[Install npm](https://www.npmjs.com/get-npm), [install
+yarn](https://yarnpkg.com/lang/en/docs/install/#mac-stable), or both as needed. You
+
+While it stands alone, this tour does on the information from the [Hello
+Blockstack tutorial](hello-blockstack). If you haven't worked through that
+tutorial, you may want to do that before continuing.
+
+
+## Install the applicaton code and retrieve the dependencies
+
+You can clone the source code with `git` or [download and unzip the code from
+the
+repository](https://github.com/blockstack/blockstack-todos/archive/master.zip).
+These instructions assume you are cloning.
+
+
+1. Install the code by cloning it.
+
+ ```
+ $ git clone git@github.com:blockstack/blockstack-todos.git
+ ```
+
+2. Change to directory to the root of the code.
+
+ ```
+ $ cd blockstack-todos
+ ```
+
+2. Use yarn to install the dependencies.
+
+
+ ```
+ $ yarn install
+ yarn install v1.9.2
+ info No lockfile found.
+ ...
+ [4/5] 🔗 Linking dependencies...
+ [5/5] 📃 Building fresh packages...
+ success Saved lockfile.
+ ✨ Done in 19.90s.
+ ```
+
+## Understand the important application files
+
+The Todo application has a basic Vue.js structure. There are several configuration files but the central programming files are in the `src` directory:
+
+| File | Description |
+|-----------------|-------------|
+| `main.js` | Application initialization. |
+| `App.vue ` | Code for handling the `authResponse`. |
+| `Landing.vue ` | Code for the initial sign on page. |
+| `Dashboard.vue` | Application data storage and user sign out. |
+
+The example application runs in a node server on your local host. In the next section, you start the application and interact with it.
+
+1. Start the application.
+
+ ```
+ $ npm run start
+ ```
+
+ You should see a simple application:
+
+ ![](images/todo-sign-in.png)
+
+ 2. Choose **Sign In with Blockstack**.
+
+
+## Understand the sign in process
+
+At startup, the Todo application detects whether the user has the Blockstack client edition
+installed or not. This is done automatically by the Blockstack API, more
+about this later. What the authenticator displays depends on which whether the user has installed the Blockstack Authenticator client edition or not.
+
+| Client edition installed | Not installed |
+|------------------|-----------------------------------|
+| ![](images/login.gif) | ![](images/login-choice.png)|
+
+If the user was logged into the Blockstack authenticator (web or client) but
+did not reset it, the web application to use the current identity:
+
+![](images/login-no-auth.png)
+
+If the user chooses **Deny**, the Blockstack authenticator opens but the user
+is not logged into the sample application.
+
+![](images/windows-browser.png)
+
+If the login to the application is successful, the user is presented with the application:
+
+![](images/todo-app.png)
+
+Clicking the **Sign In With Blockstack** button brings up a modal that prompts
+you to use an existing ID's session, create a new ID, or reset the browser with
+another ID. When Blockstack is provided an ID, it generates an _ephemeral key_
+within the application. An ephemeral key is generated for each execution of a
+key establishment process. This key is just used for the particular instance of
+the application, in this case to sign a **Sign In** request.
+
+Blockstack also generates a public key token which is sent to the authenticator
+as an `authRequest` from the authenticator to your local blockstack-core node.
+The signed authentication request is sent to Blockstack through a JSON Web
+Token. The JWT is passed in via a URL query string in the `authRequest`
+parameter:
+`https://browser.blockstack.org/auth?authRequest=j902120cn829n1jnvoa...`. To
+decode the token and see what information it holds:
+
+1. Copy the `authRequest` string from the URL.
+2. Navigate to [jwt.io](http://jwt.io/).
+3. Paste the full token there.
+
+ The output should look similar to below:
+
+ ```json
+ {
+ "jti": "3i96e3ad-0626-4e32-a316-b243154212e2",
+ "iat": 1533136622,
+ "exp": 1533140228,
+ "iss": "did:btc-addr:1Nh8oQTunbEQWjrL666HBx2qMc81puLmMt",
+ "public_keys": [
+ "0362173da080c6e1dec0653fa9a3eff5f5660546e387ce6c24u04a90c2fe1fdu73"
+ ],
+ "domain_name": "http://localhost:8080",
+ "manifest_uri": "http://localhost:8080/manifest.json",
+ "redirect_uri": "http://localhost:8080/",
+ "version": "1.2.0",
+ "do_not_include_profile": true,
+ "supports_hub_url": true,
+ "scopes": [
+ "store_write"
+ ]
+ }
+ ```
+
+>**Note**:
+> 1. The `iss` property is a decentralized identifier or `did`. This identifies you and your name to the application. The specific `did` is a `btc-addr`.
+> 2. The Blockstack JWT implementation is different from other implementations because of the underlying cryptography we employ. There are libraries in [Javascript](https://github.com/blockstack/jsontokens-js) and [Ruby](https://github.com/blockstack/ruby-jwt-blockstack) available on the Blockstack Github to allow you to work with these tokens.
+
+When the blockstack-core receives the `authRequest`, it generates a session token and
+returns an authentication response to the application. This response is similar
+to the `authRequest` above in that the `authResponse` includes a private key
+intended only for the application. This allows the application to encrypt data
+on your personal Blockstack storage.
+
+You are now logged into the Todo application!
+
+## Undder the covers in the sign in code
+
+Now, go to the underlying `blockstack-todo` code you cloned or downloaded. Sign
+in and sign out is handled in each of these files:
+
+| File | Description |
+|-----------------|-------------|
+| `App.vue ` | Handles the `authResponse`. |
+| `Landing.vue ` | Generates the `authRequest`. |
+| `Dashboard.vue` | Handles sign out. |
+
+The `src/components/Landing.vue` code calls a [`redirectToSignIn()`](https://blockstack.github.io/blockstack.js#redirectToSignIn) function which generates the `authRequest` and redirects the user to the Blockstack authenticator:
+
+```js
+signIn () {
+ const blockstack = this.blockstack
+ blockstack.redirectToSignIn()
+}
+```
+
+Once the user authenticates, the application handles the `authResponse` in the `src/App.vue` file. :
+
+```js
+if (blockstack.isUserSignedIn()) {
+ this.user = blockstack.loadUserData().profile
+} else if (blockstack.isSignInPending()) {
+ blockstack.handlePendingSignIn()
+ .then((userData) => {
+ window.location = window.location.origin
+ })
+}
+```
+
+If [`blockstack.isUserSignedIn()`](https://blockstack.github.io/blockstack.js/#isusersignedin) is true, the user was previously signed in so Blockstack pulls the data from the browser and uses it in our application. If the check on [`blockstack.isSignInPending()`](https://blockstack.github.io/blockstack.js/#issigninpending) is true, a previous `authResponse` was sent to the application but hasn't been processed yet. The `handlePendingSignIn()` function processes any pending sign in.
+
+Signout is handled in `src/components/Dashboard.vue`.
+```js
+signOut () {
+ this.blockstack.signUserOut(window.location.href)
+}
+```
+
+The method allows the application creator to decide where to redirect the user upon Sign Out:
+
+
+## Working with the application
+
+Now trying adding a few todos using the application. For example, try making a list of applications you want to see built on top of Blockstack:
+
+![](images/make-a-list.png)
+
+Each list is immediately stored in the Gaia Hub linked to your Blockstack ID.
+For more information about the Gaia hub, see the [hub
+repository](https://github.com/blockstack/gaia). You can fetch the `todos.json`
+file you just added by opening the Javascript console and running the following
+command:
+
+```Javascript
+blockstack.getFile("todos.json", { decrypt: true }).then((file) => {console.log(file)})
+```
+
+You should see a JSON with the todos you just added:
+
+```json
+[
+ {
+ "id":2,
+ "text":"Software package manager secured by the blockchain",
+ "completed":false
+ },
+ {
+ "id":1,
+ "text":"Mutable torrents with human readable names",
+ "completed":false
+ },
+ {
+ "id":0,
+ "text":"Decentralized twitter",
+ "completed":false
+ }
+]
+```
+
+
+Now, add another todo and check it off. When you fetch the newly generated file
+using the Javascript console it will reflect the change look for `"completed":true`:
+
+```json
+[
+ {
+ "id":3,
+ "text":"Blockstack Todo",
+ "completed":true
+ },
+ {
+ "id":2,
+ "text":"Software package manager secured by the blockchain",
+ "completed":false
+ },
+ ...
+]
+```
+
+Now that you have seen the application in action, dig into how it works.
+
+
+## Implementing storage
+
+Now, go to the underlying `blockstack-todo` code you cloned or downloaded. The
+application interactions with your Gaia Hub originate in the
+`src/components/Dashboard.vue` file. First lets see where the changes to the
+Todos are processed:
+
+```js
+todos: {
+ handler: function (todos) {
+ const blockstack = this.blockstack
+
+ // encryption is now enabled by default
+ return blockstack.putFile(STORAGE_FILE, JSON.stringify(todos))
+ },
+ deep: true
+}
+```
+
+Tje `todos` JSON object is passed in and the [`blockstack.putFile()`](https://blockstack.github.io/blockstack.js/#putfile) method to store it in our Gaia Hub.
+
+The code needs to read the Todo items from the storage with the [`blockstack.getFile()`](https://blockstack.github.io/blockstack.js/#getfile) method which returns a promise:
+
+```js
+fetchData () {
+ const blockstack = this.blockstack
+ blockstack.getFile(STORAGE_FILE) // decryption is enabled by default
+ .then((todosText) => {
+ var todos = JSON.parse(todosText || '[]')
+ todos.forEach(function (todo, index) {
+ todo.id = index
+ })
+ this.uidCount = todos.length
+ this.todos = todos
+ })
+},
+```
+
+The `todos` data is retrieved from the promise.
+
+
+## Summary
+
+You now have everything you need to construct complex applications complete with authentication and storage on the Decentralized Internet. Why not try coding [a sample application that accesses multiple profiles](multi-player-storage.md).
+
+If you would like to explore the Blockstack APIs, you can visit the [Blockstack Core API](https://core.blockstack.org/) documentation or the [Blockstack JS API](https://blockstack.github.io/blockstack.js).
+
+ Go forth and build!
diff --git a/_browser/.svn/pristine/55/5500a797259a620714f1c576c579f117982590db.svn-base b/_browser/.svn/pristine/55/5500a797259a620714f1c576c579f117982590db.svn-base
new file mode 100644
index 00000000..aa136ba1
Binary files /dev/null and b/_browser/.svn/pristine/55/5500a797259a620714f1c576c579f117982590db.svn-base differ
diff --git a/_browser/.svn/pristine/63/630ab4b5cbd3ff99dde5761ac5f475eb39dc3c9b.svn-base b/_browser/.svn/pristine/63/630ab4b5cbd3ff99dde5761ac5f475eb39dc3c9b.svn-base
new file mode 100644
index 00000000..738bb384
--- /dev/null
+++ b/_browser/.svn/pristine/63/630ab4b5cbd3ff99dde5761ac5f475eb39dc3c9b.svn-base
@@ -0,0 +1,288 @@
+---
+layout: usenew
+permalink: /:collection/:path.html
+---
+# Use the Blockstack Browser
+{:.no_toc}
+
+The Blockstack Browser gives users the ability to explore and use the
+decentralized applications (dapps). The decentralized applications are a new way
+to interact with the internet. Dapps give users control of their data. Data
+about them personally, name, birthdate, phone number and data about what they do
+such as visiting a website or buying an item.
+
+* TOC
+{:toc}
+
+## Understand the Blockstack Browser
+
+Through the Blockstack browser application you can create an identity. An identity
+represents you as you interact with others through Dapps. The Blockstack
+Browser is itself, a simple Dapp. It allows you to:
+
+* create one or more identities
+* send and receive bitcoin
+* manage the storage of your profile and application data
+* find and launch Dapps
+
+There are editorions of the Blockstack Browser, the web edition is an
+application you access through your web browser by simply [visit the
+applications' address](https://browser.blockstack.org/) in your computer's
+browser. You can also install the browser as a client application on your
+computer.
+
+If all you want to do is create, manage, and fund an identity and then interact
+with Dapps, you can simply use the web edition. If you have concerns about net
+censorship, hightened security concerns, or develop a Dapp yourself, you may
+want to download and install the browser's client edition.
+
+## Using the Browser on public computers
+
+Before you use the web application, it is important to note that once you log
+into the application with the brower, your session does not expire until you
+choose **Settings > RESET BROWSER**. For this reason, you should be careful
+when using the browser on public computers.
+
+If you are in a library, for example, and log into the browser, simply
+closing the tab or even rebooting the computer does not log you out. Instead,
+you should be sure to choose **Settings > RESET BROWSER** before leaving the web
+application.
+
+For more informatin about your identity and the browser, see [Get and use a Blockstack IDs](ids-introduction).
+
+## Install the client edition
+
+Remember, for most users the Blockstack Browser web application should
+suffice. You only need to install the client if you have additional, advanced
+concerns about Internet or identity. Though not required, some Dapp developrs
+may find it useful to install the client edition.
+
+The Blockstack Browser installer is a _multiple-context_ installer. If you
+run it as a user, the installation is avalable only for that user. If you
+install as administrator, the installation installs for all users. To find an
+installer for your operating system, visit [the Blockstack install
+page](https://blockstack.org/install).
+
+### On Mac
+
+Installation requires that you have macOS High Sierra 10.12 or higher. Do the following to install:
+
+1. Download the OSX installer from [the browser installation page](https://blockstack.org/install).
+2. Double-click the downloaded DMG file to launch the installer.
+
+ ![](images/ubuntu-browser.png)
+
+3. Drag the Blockstack.app to the `Applications` folder.
+4. Double-click the Blockstack.app to launch it.
+
+ The system displays a notice about opening the file:
+
+ ![](images/dmg-notice.png)
+
+5. Choose **Open**.
+
+ The system opens your default browser with the Blockstack Browser
+ application, running from your machine (localhost). You'll also see the
+ Blockstack icon in your machine's
+
+ ![](images/browser-on-mac.png)
+
+ If you have loaded an identity already via the Blockstack web application,
+ you are already logged into the local application:
+
+ ![](images/browser-on-mac-1.png)
+
+
+### On Windows
+
+Installation requires that you have Windows 10 or higher. Do the following to
+install:
+
+1. Download the Windows installer from from [the browser installation page](https://blockstack.org/install).
+2. Double-click the installer package to launch it.
+
+ ![](images/windows-installer.png)
+
+3. Open the Wiindows **Start** menu and click on the recently added **Blockstack Browser**.
+
+ ![](images/windows-start.png)
+
+ The system displays a Windows Security Alert.
+
+ ![](images/windows-security.png)
+
+4. Choose to **Allow access**.
+
+ The system opens in the Blockstack Browser application.
+
+ ![](images/windows-browser.png)
+
+
+### On Linux
+
+The Blockstack installation on Linux requires Docker. Before installing
+Blockstack, [install the version of Docker appropriate for your operating system](https://docs.docker.com/install/).
+
+>**Note**: The Blockstack script used in this procedure runs `docker` commands. Depending on how you installed and configure Dockered on your system, it may or may not be necessary to have `root` or `sudo` privileges. For this reason, the commands below show the use of `sudo` when interacting with the script or the `docker` executable. If your installation allows running Docker with lower privileges, you can omit it.
+
+
+1. Download the Linux installer from from [the browser installation page](https://blockstack.org/install).
+
+ This downloads a `Blockstack-for-Linux-v0.30.0.sh` script to your local drive.
+
+2. Open a terminal and navigate to the directory containing the downloaded script.
+
+ When the script downloads, it is not executable.
+
+3. Set the executable bit on the file.
+
+ ```bash
+ $ chmod u+x Blockstack-for-Linux-v0.309.0.0.sh
+ ```
+
+4. Enter the command without any arguments to see the available subcommands.
+
+ ```bash
+ $ sudo ./Blockstack-for-Linux-v0.309.0.0.sh
+ blockstack docker launcher commands:
+ Install-protocol-handler -> install a protocol handler for blockstack:// links
+ ...
+ ```
+
+5. Use the script to `pull` the Blockstack Docker images you need.
+
+
+ ```bash
+ $ sudo ./Blockstack-for-Linux-v0.309.0.0.sh pull
+ ```
+
+ Depending on your network speed, this can take some time.
+
+7. Use the `docker image ls` command to confirm you have the image.
+
+ ```bash
+ $ sudo docker image Is
+ REPOSITORY TAG IMAGE ID CREATED
+ quay.io/blockstack/blockstack-browser v0.30.0 ad05fd844f59 2 days ago
+ ```
+
+8. Install the protocol handler
+
+ ```bash
+ $ sudo ./Blockstack-for-Linux-vO.30.0.sh install-protocol-handler
+ Registering protocol handler
+ ```
+
+9. Start the Blockstack containers.
+
+ ```bash
+ $ sudo ./Blockstack-for-Linux-vO.30.0.sh start
+ c3092592e59abe3559fdb49d070a7aa5e99165c7d9f2flla20ecaf4e0dfc2f46
+ cd92f61ae473d54398da987f5023f5462b29c03f08584ebb3c9fIbb4cd790c69
+ Registering protocol handler
+ ```
+
+ The system launches the Blockstack Browser application for you.
+
+ ![](images/ubuntu-browser.png)
+
+Until you stop the Blockstack containers, the application will continue to run
+on your system. To display the status of the Blockstack containers, you can use
+the `docker container ls` command.
+
+{% raw %}
+```bash
+$ sudo docker container ls --format '{{.ID}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}\t{{.Names}}'
+```
+{% endraw %}
+
+Use `./Blockstack-for-Linux-vO.30.0.sh stop` to stop the Blockstack Browser and its containers.
+
+
+## Uninstall the browser
+
+If you installed the browser using an installer, follow the instructions for
+your operating system.
+
+### On Mac
+
+1. Quit the Blockstack application if it is running.
+
+ ![](images/quit-blockstack.png)
+
+2. Check if you have a Blockstack device and eject it if you do.
+
+ ![](images/eject-blockstack.png)
+
+3. Use the Finder to open the **Applications** folder.
+4. Locate the Blockstack application.
+5. Open your `Applications` folder and locate the **Blockstack.app**.
+6. Drag the appliation to the trash.
+7. Delete the `/Users/USERNAME/Library/Application Support/Blockstack` folder.
+
+ From the command line:
+
+ ```bash
+ $ rm -r /Users/moxiegirl/Library/Application\ Support/Blockstack
+ ```
+
+### On Windows
+
+1. Open the **Start** menu.
+2. Click **Settings > System**.
+3. Open for the **Apps & features** item.
+
+ ![](images/eject-blockstack.png)
+
+4. Locate the **Blockstack Browser** and choose **Uninstall**.
+
+ ![](images/browser-uninstall.png)
+
+
+### On Linux
+
+Your Blockstack instalaltion relies on Docker containers and their associated
+images. It also includes a supporting protocol handler you must remove. If you
+installed Docker so that you can run Blockstack, you can uninstall Docker as well,
+but that is not explained here.
+
+Do the following to uninstall Blockstack:
+
+1. Stop and remove the Docker containers if they are running.
+
+ ```bash
+ $ sudo ./Blockstack-for-Linux-vO.30.0.sh stop
+ stopping the running blockstack-browser containers
+ 69a686799d4f
+ 56fc6189ff97
+ 69a686799d4f
+ 56fc6189ff97
+ ```
+
+2. Remove the associated Blockstack images.
+
+ ```bash
+ $ sudo docker image ls
+ REPOSITORY TAG IMAGE ID CREATED
+ quay.io/blockstack/blockstack-browser v0.30.0 ad05fd844f59 3 days ago
+ $ sudo docker image rm ad05fd844f59
+ Untagged : quay.io/blockstack/blockstack- browser :vO.30.0
+ Untagged: quay.io/blockstack/blockstack-browser@sha256:b20c9514c56b99398fd4946af39e7537b807e85694943ac3b8807dlb3625833b
+ Deleted: Sha256:ad05fd844f5948blee06a0a09228df946478393c0a7588cbc65dlb8817f5b34e
+ Deleted: Sha256:7c3d0043f2ba01cf285f3fe09701b086c349b6380c2e42f25b31ac65c6626ec8
+ Deleted: sha256:54ea2aa7d7d000e7483f299eeca9e5466fa86231f4cd4cld3c3096d97e61c5df
+ Deleted: sha256:38e61054355adefc3c2de031462114a9946cfc0e44444a38a27d0f115aba0da2
+ ....
+ ```
+
+3. Use the script to remove the protocol handler
+
+ ```bash
+ $ sudo ./Blockstack-for-Linux-vO.30.0.sh remove-protocol-handler
+ ```
+
+4. Delete the script.
+
+ ```bash
+ $ rm Blockstack-for-Linux-vO.30.0.sh
+ ```
diff --git a/_browser/.svn/pristine/63/6326880dd17c45162090e3bb4902adefbccfcb15.svn-base b/_browser/.svn/pristine/63/6326880dd17c45162090e3bb4902adefbccfcb15.svn-base
new file mode 100644
index 00000000..cd6b3b6a
Binary files /dev/null and b/_browser/.svn/pristine/63/6326880dd17c45162090e3bb4902adefbccfcb15.svn-base differ
diff --git a/_browser/.svn/pristine/64/6462fdc5109daa02e29fbf38f8602f7425387275.svn-base b/_browser/.svn/pristine/64/6462fdc5109daa02e29fbf38f8602f7425387275.svn-base
new file mode 100644
index 00000000..8fa411cb
--- /dev/null
+++ b/_browser/.svn/pristine/64/6462fdc5109daa02e29fbf38f8602f7425387275.svn-base
@@ -0,0 +1,812 @@
+---
+layout: learn
+permalink: /:collection/:path.html
+---
+# Blockstack Storage Tutorial
+{:.no_toc}
+
+In this tutorial, you build a micro-blogging application using multi-player Gaia
+storage. Gaia is Blockstack's [decentralized high-performance storage
+system](https://github.com/blockstack/gaia). The tutorial contains the following
+topics:
+
+* TOC
+{:toc}
+
+This tutorial does not teach you about authentication. That is covered in depth [in the hello-blockstack tutorial](hello-blockstack).
+
+
+
+
+## About this tutorial and the prerequisites you need
+
+At minimum, Blockstack requires macOS High Sierra. This tutorial was written for
+a user running macOS High Sierra 10.13.4. The application you build is a
+React.js application that is completely decentralized and server-less. While
+not strictly required to follow along, basic familiarity with React.js is
+helpful.
+
+When complete, the app is capable of the following:
+
+- authenticating users using Blockstack
+- posting new statuses
+- displaying statuses in the user profile
+- looking up the profiles and statuses of other users
+
+The basic identity and storage services are provided by `blockstack.js`. To test
+the application, you need to have already [registered a Blockstack ID](ids-introduction).
+
+The tutorial relies on the `npm` dependency manager. Before you begin, verify
+you have installed `npm` using the `which` command.
+
+```bash
+$ which npm
+/usr/local/bin/npm
+```
+
+If you don't find `npm` in your system, [install
+it](https://www.npmjs.com/get-npm). Finally, if you get stuck at any point
+while working on the tutorial, the completed [source code is available for
+you](https://github.com/larrysalibra/publik) to check your work against.
+
+## Use npm to install Yeoman and the Blockstack App Generator
+
+You use `npm` to install Yeoman. Yeoman is a generic scaffolding system that
+helps users rapidly start new projects and streamline the maintenance of
+existing projects.
+
+
+1. Install Yeoman.
+
+ ```bash
+ npm install -g yo
+ ```
+2. Install the Blockstack application generator.
+
+ ```bash
+ npm install -g generator-blockstack
+ ```
+
+
+
+## Generate and launch the public application
+
+In this section, you build an initial React.js application called Publik.
+
+1. Create a the `publik` directory.
+
+ ```bash
+ mkdir publik
+ ```
+
+2. Change into your new directory.
+
+ ```bash
+ cd publik
+ ```
+
+3. Use Yeoman and the Blockstack application generator to create your initial `publik` application.
+
+ ```bash
+ yo blockstack:react
+ ```
+
+ You should see several interactive prompts.
+
+ ```bash
+ $ yo blockstack:react
+ ? ==========================================================================
+ We're constantly looking for ways to make yo better!
+ May we anonymously report usage statistics to improve the tool over time?
+ More info: https://github.com/yeoman/insight & http://yeoman.io
+ ========================================================================== No
+
+ _-----_ ╭──────────────────────────╮
+ | | │ Welcome to the │
+ |--(o)--| │ Blockstack app │
+ `---------´ │ generator! │
+ ( _´U`_ ) ╰──────────────────────────╯
+ /___A___\ /
+ | ~ |
+ __'.___.'__
+ ´ ` |° ´ Y `
+
+ ? Are you ready to build a Blockstack app in React? (Y/n)
+ ```
+
+4. Respond to the prompts to populate the initial app.
+
+ After the process completes successfully, you see a prompt similar to the following:
+
+ ```bash
+ [fsevents] Success:
+ "/Users/theuser/repos/publik/node_modules/fsevents/lib/binding/Release/node-v59-darwin-x64/fse.node"
+ is installed via remote npm notice created a lockfile as package-lock.json.
+ You should commit this file. added 1060 packages in 26.901s
+ ```
+
+5. Run the initial application.
+
+ ```bash
+ npm start
+ ```
+
+ The system prompts you to accept incoming connections.
+
+ ![Network Connection](./images/network-connections.gif)
+
+6. Choose **Allow**.
+
+7. Open your browser to `http://localhost:8080`.
+
+ You should see a simple React app.
+
+ ![](images/initial-app.gif)
+
+8. Choose **Sign In with Blockstack**.
+
+ The application tells you it will **Read your basic info**.
+
+ ![](images/login.png)
+
+Leave your new application running and move onto the next section.
+
+## Add the `publish_data` scope to sign in requests
+
+Every app that uses Gaia storage must add itself to the user's `profile.json`
+file. The Blockstack browser does this automatically when the `publish_data`
+scope is requested during authentication. For this application, the user files
+stored on Gaia are made visible to others via the `apps` property in the user's
+`profile.json` file.
+
+Modify your authentication request to include the `publish_data` scope.
+
+1. Open `src/components/App.jsx` file.
+
+2. Locate the `handleSignIn` handler method.
+
+ ```javascript
+ handleSignIn(e) {
+ e.preventDefault();
+ redirectToSignIn();
+ }
+ ```
+
+2. Modify the method to this:
+
+ ```javascript
+ handleSignIn(e) {
+ e.preventDefault();
+ const origin = window.location.origin
+ redirectToSignIn(origin, origin + '/manifest.json', ['store_write', 'publish_data'])
+ }
+ ```
+
+ By default, authentication requests include the `store_write` scope which
+ enables storage. This is what allows you to store information to Gaia.
+
+3. Save your changes.
+4. Go back to your app at `http://localhost:8080/`.
+5. Log out and sign in again.
+
+ The authentication request now prompts the user for permission to **Publish
+ data stored for the app**.
+
+ ![](images/publish-data-perm.png)
+
+## Understand Gaia storage methods
+
+Once you authenticate a user with `store_write` and `publish_data`, you can
+begin to manage data for your users. Blockstack JS provides two methods
+`getFile()` and `putFile()` for interacting with Gaia storage. The storage
+methods support all file types. This means you can store SQL, Markdown, JSON, or
+even a custom format.
+
+You can create a meaningful and complex data layer using these two methods.
+Before creating an application, consider fundamental data architecture and make
+some decisions about how you’re modeling data. For example, consider building a
+simple grocery list app. A user should be able to create, read, update, and
+delete grocery lists.
+
+A single file collection stores items as an array nested inside each grocery
+list:
+
+```js
+// grocerylists.json
+{
+ "3255": {
+ "items": [
+ "1 Head of Lettuce",
+ "Haralson apples"
+ ]
+ },
+ // ...more lists with items
+}
+```
+
+This is conceptually the simplest way to manage grocery lists. When you read a
+`/grocerylists.json` file with `getFile()`, you get back one or more grocery
+lists and their items. When you write a single list, the `putFile()` method
+overwrites the entire list. So, a write operation for a new or updated grocery
+list must submit all existings lists as well.
+
+Further, because this runs on the client where anything can go wrong. If the
+client-side code encounters a parsing error with a user-input value and you
+could overwrite the entire file with:
+
+`line 6: Parsing Error: Unexpected token.`
+
+Further, a single file makes pagination impossible and if your app stores a
+single file for all list you have less control over file permissions. To avoid
+these issues, you can create an index file that stores an array of IDs. These
+IDs point to a name of another file in a `grocerylists` folder.
+
+![](images/multiple-lists.png)
+
+This design allows you to get only the files you need and avoid accidentally
+overwriting all lists. Further, you’re only updating the index file when you add
+or remove a grocery list; updating a list has no impact.
+
+
+## Add support for user status submission and lookup
+
+In this step, you add three `blockstack.js` methods that support posting of "statuses". These are the `putFile()`, `getFile()`, and `lookupProfile()` methods.
+
+1. Open the `src/components/Profile.jsx` file.
+
+2. Expand the `import from blockstack` statement with data methods.
+
+ The `Person` object holds a Blockstack profile. Add `putFile`, `getFile`,
+ and `lookupProfile` after `Person`.
+
+ When you are done, the import statement should look like the following:
+
+ ```javascript
+ import {
+ isSignInPending,
+ loadUserData,
+ Person,
+ getFile,
+ putFile,
+ lookupProfile
+ } from 'blockstack';
+ ```
+
+3. Replace the `constructor()` initial state so that it holds the key properties required by the app.
+
+ This code constructs a Blockstack `Person` object to hold the profile. Your constructor should look like this:
+
+ ```javascript
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ person: {
+ name() {
+ return 'Anonymous';
+ },
+ avatarUrl() {
+ return avatarFallbackImage;
+ },
+ },
+ username: "",
+ newStatus: "",
+ statuses: [],
+ statusIndex: 0,
+ isLoading: false
+ };
+ }
+ ```
+
+
+4. Locate the `render()` method.
+5. Modify the `render()` method to add a text input and submit button to the application.
+
+ The following code echos the `person.name` and `person.avatarURL`
+ properties from the profile on the display:
+
+ ```javascript
+ render() {
+ const { handleSignOut } = this.props;
+ const { person } = this.state;
+ const { username } = this.state;
+
+ return (
+ !isSignInPending() && person ?
+
: null
+ );
+ }
+ ```
+
+ This code allows the application to post statuses. It also displays the
+ user's Blockstack ID. To display this, your app must extract the ID from the
+ user profile data.
+
+6. Locate the `componentWillMount()` method.
+7. Add the `username` property below the `person` property.
+
+ You'll use the Blockstack `loadUserData()` method to access the `username`.
+
+
+ ```javascript
+ componentWillMount() {
+ this.setState({
+ person: new Person(loadUserData().profile),
+ username: loadUserData().username
+ });
+ }
+ ```
+
+7. Add two methods to handle the status input events:
+
+ ```javascript
+ handleNewStatusChange(event) {
+ this.setState({newStatus: event.target.value})
+ }
+
+ handleNewStatusSubmit(event) {
+ this.saveNewStatus(this.state.newStatus)
+ this.setState({
+ newStatus: ""
+ })
+ }
+ ```
+
+8. Add a `saveNewStatus()` method to save the new statuses.
+
+ ```javascript
+ saveNewStatus(statusText) {
+ let statuses = this.state.statuses
+
+ let status = {
+ id: this.state.statusIndex++,
+ text: statusText.trim(),
+ created_at: Date.now()
+ }
+
+ statuses.unshift(status)
+ const options = { encrypt: false }
+ putFile('statuses.json', JSON.stringify(statuses), options)
+ .then(() => {
+ this.setState({
+ statuses: statuses
+ })
+ })
+ }
+ ```
+
+9. Save the `Profile.jsk` file.
+
+ After the application compiles successfully, your application should appears as follows:
+
+ ![](images/display-complete.png)
+
+10. Enter your status in the text box and press the **Submit** button.
+
+ At this point, nothing is blogged. In the next section you add code to display
+ the statuses back to the user as a blog entry.
+
+## Fetch and display statuses
+
+Update `Profile.jsx` again.
+
+1. Go back to the `render()` method.
+2. Locate the `
` containing the text input and **Submit** button.
+3. Right after this opening `div` element, add this block.
+
+ ```javascript
+
+ ```
+ This loads existing state. Your code needs to fetch statuses on page load.
+
+4. Add a new method called `fetchData()` after the `statuses.unshift(status)` section.
+
+ ```javascript
+
+ fetchData() {
+ this.setState({ isLoading: true })
+ const options = { decrypt: false }
+ getFile('statuses.json', options)
+ .then((file) => {
+ var statuses = JSON.parse(file || '[]')
+ this.setState({
+ person: new Person(loadUserData().profile),
+ username: loadUserData().username,
+ statusIndex: statuses.length,
+ statuses: statuses,
+ })
+ })
+ .finally(() => {
+ this.setState({ isLoading: false })
+ })
+ }
+ ```
+
+5. Call `fetchData()` from the `componentDidMount()` method
+
+ ```javascript
+
+ componentDidMount() {
+ this.fetchData()
+ }
+ ```
+
+6. Save the file.
+
+ After the application compiles successfully, users are able to **Submit**
+ multiple statuses and review them in the app.
+
+ ![](images/saving-status.png)
+
+## Change the style
+
+1. Edit the `src/styles/style.css` file.
+2. Replace the content with the following:
+
+
+ ```css
+ /* Globals */
+ a,a:focus,a:hover{color:#fff;}
+ html,body{height:100%;text-align:center;background-color:#191b22;}
+ body{color:#fff}
+ .hide{display:none;}
+ .landing-heading{font-family:'Lato',Sans-Serif;font-weight:400;}
+
+ /* Buttons */
+ .btn{font-family:'Lato',Sans-Serif;padding:0.5625rem 2.5rem;font-size:0.8125rem;font-weight:400;line-height:1.75rem;border-radius:0!important;-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;-ms-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;}
+ .btn-lg{font-size:1.5rem;padding:0.6875rem 3.4375rem;line-height:2.5rem;}
+ .btn:focus,.btn:active:focus,.btn.active:focus{outline:none;}
+ .btn-primary{color:#fff;border:1px solid #2C96FF;background-color:#2C96FF;}
+ .btn-primary:hover,.btn-primary:focus,.btn-primary:active{color:#fff;border:1px solid #1a6ec0;background-color:#1a6ec0;}
+
+ /* Avatar */
+ .avatar{width:100px;height:100px;}
+ .avatar-section{margin-bottom:25px;display:flex;text-align:left;}
+ .username{margin-left:20px;}
+
+ /* Scaffolding */
+ .site-wrapper{display:table;width:100%;height:100vh;min-height:100%;}
+ .site-wrapper-inner{display:flex;flex-direction:column;justify-content:center;margin-right:auto;margin-left:auto;width:100%;height:100vh;}
+ .panel-authed{padding:0 0 0 0;}
+
+ /* Home button */
+ .btn-home-hello{position:absolute;font-family:'Source Code Pro',monospace;font-size:11px;font-weight:400;color:rgba(255,255,255,0.85);top:15px;left:15px;padding:3px 20px;background-color:rgba(255,255,255,0.15);border-radius:6px;-webkit-box-shadow:0px 0px 20px 0px rgba(0,0,0,0.15);-moz-box-shadow:0px 0px 20px 0px rgba(0,0,0,0.15);box-shadow:0px 0px 20px 0px rgba(0,0,0,0.15);}
+
+ /* Input */
+ input, textarea{color:#000;padding:10px;}
+ .input-status{width:100%;height:70px;border-radius:6px;}
+ .new-status{text-align:right;}
+
+ /* Statuses */
+ .statuses{padding-top:30px;}
+ .status{margin:15px 0px;padding:20px;background-color:#2e2e2e;border-radius:6px}
+ ```
+
+3. Save and close the `src/styles/style.css` file.
+
+ After the application compiles, you should see the following:
+
+ ![Multi-reader storage authentication](images/multi-player-storage-status.png)
+
+
+At this point, you have a basic micro-blogging app that users can use to post and
+view statuses. However, there's no way to view other users' statuses. You'll add
+that in the next section.
+
+## Lookup user profiles
+
+Let's now modify the `Profile.jsx` file to display profiles of other users. You'll
+be using the `lookupProfile()` method that you added to the `import` statement
+earlier. `lookupProfile()` takes a single parameter that is the Blockstack ID of
+the profile and returns a profile object.
+
+### Add a new route
+
+Make some changes to the routing structure of your app so that users can view
+other users' profiles by visiting `http://localhost:8080/other_user.id`
+
+
+1. Make sure you are in the root of your `publik` project.
+2. Install `react-router`:
+
+ ```bash
+ npm install --save react-router-dom
+ ```
+
+3. Edit `src/index.js` file.
+4. Add an `import` to the file at the top:
+
+ ```javascript
+ import { BrowserRouter } from 'react-router-dom'
+ ```
+
+5. Change the `ReactDOM.render()` method in `src/index.js` to:
+
+ ```javascript
+ ReactDOM.render((
+
+
+
+ ), document.getElementById('root'));
+ ```
+6. Save and close the `src/index.js` file.
+7. Edit the `src/components/App.jsx` file.
+8. Add the new route by importing the `Switch` and `Route` components from `react-router-dom`:
+
+ ```javascript
+ import { Switch, Route } from 'react-router-dom'
+ ```
+9. Locate this line below in the `render()` method:
+
+ ```javascript
+ :
+ ```
+
+10. Replace it with the following:
+
+ ```javascript
+ :
+
+
+ }
+ />
+
+ ```
+
+ This sets up a route and captures the route parameter the app will use as the profile lookup username.
+
+11. Save and close the the `src/components/App.jsx` file.
+
+
+### Add a rule to process URL paths with . (dot)
+
+You also need to add a rule to your webpack config so that you can properly
+process URL paths that contain the `.` (dot) character for example,
+`http://localhost:8080/other_user.id`
+
+**NOTE**: In a production app, you must ensure the web server is configured to handle this.
+
+
+1. Open `webpack.config.js` in the root project directory and locate the following line:
+
+ ```javascript
+ historyApiFallback: true,
+ ```
+
+2. Replace it with this:
+
+ ```javascript
+ historyApiFallback: {
+ disableDotRule: true
+ },
+ ```
+
+ You will need to run `npm start` again for this change to take effect. Don't
+ worry, there is a later step for that to remind you.
+
+3. Save and close the `webpack.config.js` file.
+
+4. Edit the `src/components/Profile.jsx` file.
+5. Add a single method that determines if the app is viewing the local user's profile or another user's profile.
+
+ ```javascript
+ isLocal() {
+ return this.props.match.params.username ? false : true
+ }
+ ```
+
+ You use `isLocal()` to check if the user is viewing the local user profile or another user's profile. If it's the local user profile, the app runs the `getFile()` function you added in an earlier step. Otherwise, the app looks up the profile belonging to the `username` using the `lookupProfile()` method.
+
+6. Modify the `fetchData()` method like so:
+
+ ```javascript
+ fetchData() {
+ this.setState({ isLoading: true })
+ if (this.isLocal()) {
+ const options = { decrypt: false }
+ getFile('statuses.json', options)
+ .then((file) => {
+ var statuses = JSON.parse(file || '[]')
+ this.setState({
+ person: new Person(loadUserData().profile),
+ username: loadUserData().username,
+ statusIndex: statuses.length,
+ statuses: statuses,
+ })
+ })
+ .finally(() => {
+ this.setState({ isLoading: false })
+ })
+ } else {
+ const username = this.props.match.params.username
+
+ lookupProfile(username)
+ .then((profile) => {
+ this.setState({
+ person: new Person(profile),
+ username: username
+ })
+ })
+ .catch((error) => {
+ console.log('could not resolve profile')
+ })
+ }
+ }
+ ```
+
+ **NOTE**: For `https` deployments, the default Blockstack Core API endpoint for name
+ lookups should be changed to point to a core API served over `https`.
+ Otherwise, name lookups fail due to browsers blocking mixed content.
+ Refer to the [Blockstack.js
+ documentation](http://blockstack.github.io/blockstack.js/#getfile) for
+ details.
+
+7. Add the following block to `fetchData()` right after the call to `lookupProfile(username)... catch((error)=>{..}` block:
+
+ ```javascript
+ const options = { username: username, decrypt: false }
+ getFile('statuses.json', options)
+ .then((file) => {
+ var statuses = JSON.parse(file || '[]')
+ this.setState({
+ statusIndex: statuses.length,
+ statuses: statuses
+ })
+ })
+ .catch((error) => {
+ console.log('could not fetch statuses')
+ })
+ .finally(() => {
+ this.setState({ isLoading: false })
+ })
+ ```
+
+ This fetches the user statuses.
+
+ Finally, you must conditionally render the logout button, status input textbox, and submit button so they don't show up when viewing another user's profile.
+
+8. Replace the `render()` method with the following:
+
+ ```javascript
+ render() {
+ const { handleSignOut } = this.props;
+ const { person } = this.state;
+ const { username } = this.state;
+
+ return (
+ !isSignInPending() && person ?
+
: null
+ );
+ }
+ ```
+
+ ### This checks to ensure that users are viewing their own profile, by wrapping the **Logout** button and inputs with the `{isLocal() && ...}` condition.
+
+### Put it all together
+
+1. Stop the running application by sending a CTL-C.
+2. Restart the application so that the disabling of the `.` (dot) rule takes effect.
+
+ ```bash
+ npm start
+ ```
+
+3. Point your browser to `http://localhost:8080/your_blockstack.id` to see the final application.
+
+
+
+## Wrapping up
+
+Congratulations, you are all done! We hope you've enjoyed learning a bit more
+about Blockstack. To use a working version of the app go
+[here](http://publik.ykliao.com).
diff --git a/_browser/.svn/pristine/65/65ae54036b4f6a2a5c29057ecf62cd91b4b3f506.svn-base b/_browser/.svn/pristine/65/65ae54036b4f6a2a5c29057ecf62cd91b4b3f506.svn-base
new file mode 100644
index 00000000..4cbade8a
--- /dev/null
+++ b/_browser/.svn/pristine/65/65ae54036b4f6a2a5c29057ecf62cd91b4b3f506.svn-base
@@ -0,0 +1,812 @@
+---
+layout: learn
+permalink: /:collection/:path.html
+---
+# Manage Data with Gaia
+{:.no_toc}
+
+In this tutorial, you build a micro-blogging application using multi-player Gaia
+storage. Gaia is Blockstack's [decentralized high-performance storage
+system](https://github.com/blockstack/gaia). The tutorial contains the following
+topics:
+
+* TOC
+{:toc}
+
+This tutorial does not teach you about authentication. That is covered in depth [in the hello-blockstack tutorial](hello-blockstack.md).
+
+
+
+
+## About this tutorial and the prerequisites you need
+
+At minimum, Blockstack requires macOS High Sierra. This tutorial was written for
+a user running macOS High Sierra 10.13.4. The application you build is a
+React.js application that is completely decentralized and server-less. While
+not strictly required to follow along, basic familiarity with React.js is
+helpful.
+
+When complete, the app is capable of the following:
+
+- authenticating users using Blockstack
+- posting new statuses
+- displaying statuses in the user profile
+- looking up the profiles and statuses of other users
+
+The basic identity and storage services are provided by `blockstack.js`. To test
+the application, you need to have already [registered a Blockstack ID](ids-introduction.md).
+
+The tutorial relies on the `npm` dependency manager. Before you begin, verify
+you have installed `npm` using the `which` command.
+
+```bash
+$ which npm
+/usr/local/bin/npm
+```
+
+If you don't find `npm` in your system, [install
+it](https://www.npmjs.com/get-npm). Finally, if you get stuck at any point
+while working on the tutorial, the completed [source code is available for
+you](https://github.com/larrysalibra/publik) to check your work against.
+
+## Use npm to install Yeoman and the Blockstack App Generator
+
+You use `npm` to install Yeoman. Yeoman is a generic scaffolding system that
+helps users rapidly start new projects and streamline the maintenance of
+existing projects.
+
+
+1. Install Yeoman.
+
+ ```bash
+ npm install -g yo
+ ```
+2. Install the Blockstack application generator.
+
+ ```bash
+ npm install -g generator-blockstack
+ ```
+
+
+
+## Generate and launch the public application
+
+In this section, you build an initial React.js application called Publik.
+
+1. Create a the `publik` directory.
+
+ ```bash
+ mkdir publik
+ ```
+
+2. Change into your new directory.
+
+ ```bash
+ cd publik
+ ```
+
+3. Use Yeoman and the Blockstack application generator to create your initial `publik` application.
+
+ ```bash
+ yo blockstack:react
+ ```
+
+ You should see several interactive prompts.
+
+ ```bash
+ $ yo blockstack:react
+ ? ==========================================================================
+ We're constantly looking for ways to make yo better!
+ May we anonymously report usage statistics to improve the tool over time?
+ More info: https://github.com/yeoman/insight & http://yeoman.io
+ ========================================================================== No
+
+ _-----_ ╭──────────────────────────╮
+ | | │ Welcome to the │
+ |--(o)--| │ Blockstack app │
+ `---------´ │ generator! │
+ ( _´U`_ ) ╰──────────────────────────╯
+ /___A___\ /
+ | ~ |
+ __'.___.'__
+ ´ ` |° ´ Y `
+
+ ? Are you ready to build a Blockstack app in React? (Y/n)
+ ```
+
+4. Respond to the prompts to populate the initial app.
+
+ After the process completes successfully, you see a prompt similar to the following:
+
+ ```bash
+ [fsevents] Success:
+ "/Users/theuser/repos/publik/node_modules/fsevents/lib/binding/Release/node-v59-darwin-x64/fse.node"
+ is installed via remote npm notice created a lockfile as package-lock.json.
+ You should commit this file. added 1060 packages in 26.901s
+ ```
+
+5. Run the initial application.
+
+ ```bash
+ npm start
+ ```
+
+ The system prompts you to accept incoming connections.
+
+ ![Network Connection](./images/network-connections.gif)
+
+6. Choose **Allow**.
+
+7. Open your browser to `http://localhost:8080`.
+
+ You should see a simple React app.
+
+ ![](images/initial-app.gif)
+
+8. Choose **Sign In with Blockstack**.
+
+ The application tells you it will **Read your basic info**.
+
+ ![](images/login.png)
+
+Leave your new application running and move onto the next section.
+
+## Add the `publish_data` scope to sign in requests
+
+Every app that uses Gaia storage must add itself to the user's `profile.json`
+file. The Blockstack browser does this automatically when the `publish_data`
+scope is requested during authentication. For this application, the user files
+stored on Gaia are made visible to others via the `apps` property in the user's
+`profile.json` file.
+
+Modify your authentication request to include the `publish_data` scope.
+
+1. Open `src/components/App.jsx` file.
+
+2. Locate the `handleSignIn` handler method.
+
+ ```javascript
+ handleSignIn(e) {
+ e.preventDefault();
+ redirectToSignIn();
+ }
+ ```
+
+2. Modify the method to this:
+
+ ```javascript
+ handleSignIn(e) {
+ e.preventDefault();
+ const origin = window.location.origin
+ redirectToSignIn(origin, origin + '/manifest.json', ['store_write', 'publish_data'])
+ }
+ ```
+
+ By default, authentication requests include the `store_write` scope which
+ enables storage. This is what allows you to store information to Gaia.
+
+3. Save your changes.
+4. Go back to your app at `http://localhost:8080/`.
+5. Log out and sign in again.
+
+ The authentication request now prompts the user for permission to **Publish
+ data stored for the app**.
+
+ ![](images/publish-data-perm.png)
+
+## Understand Gaia storage methods
+
+Once you authenticate a user with `store_write` and `publish_data`, you can
+begin to manage data for your users. Blockstack JS provides two methods
+`getFile()` and `putFile()` for interacting with Gaia storage. The storage
+methods support all file types. This means you can store SQL, Markdown, JSON, or
+even a custom format.
+
+You can create a meaningful and complex data layer using these two methods.
+Before creating an application, consider fundamental data architecture and make
+some decisions about how you’re modeling data. For example, consider building a
+simple grocery list app. A user should be able to create, read, update, and
+delete grocery lists.
+
+A single file collection stores items as an array nested inside each grocery
+list:
+
+```js
+// grocerylists.json
+{
+ "3255": {
+ "items": [
+ "1 Head of Lettuce",
+ "Haralson apples"
+ ]
+ },
+ // ...more lists with items
+}
+```
+
+This is conceptually the simplest way to manage grocery lists. When you read a
+`/grocerylists.json` file with `getFile()`, you get back one or more grocery
+lists and their items. When you write a single list, the `putFile()` method
+overwrites the entire list. So, a write operation for a new or updated grocery
+list must submit all existings lists as well.
+
+Further, because this runs on the client where anything can go wrong. If the
+client-side code encounters a parsing error with a user-input value and you
+could overwrite the entire file with:
+
+`line 6: Parsing Error: Unexpected token.`
+
+Further, a single file makes pagination impossible and if your app stores a
+single file for all list you have less control over file permissions. To avoid
+these issues, you can create an index file that stores an array of IDs. These
+IDs point to a name of another file in a `grocerylists` folder.
+
+![](images/multiple-lists.png)
+
+This design allows you to get only the files you need and avoid accidentally
+overwriting all lists. Further, you’re only updating the index file when you add
+or remove a grocery list; updating a list has no impact.
+
+
+## Add support for user status submission and lookup
+
+In this step, you add three `blockstack.js` methods that support posting of "statuses". These are the `putFile()`, `getFile()`, and `lookupProfile()` methods.
+
+1. Open the `src/components/Profile.jsx` file.
+
+2. Expand the `import from blockstack` statement with data methods.
+
+ The `Person` object holds a Blockstack profile. Add `putFile`, `getFile`,
+ and `lookupProfile` after `Person`.
+
+ When you are done, the import statement should look like the following:
+
+ ```javascript
+ import {
+ isSignInPending,
+ loadUserData,
+ Person,
+ getFile,
+ putFile,
+ lookupProfile
+ } from 'blockstack';
+ ```
+
+3. Replace the `constructor()` initial state so that it holds the key properties required by the app.
+
+ This code constructs a Blockstack `Person` object to hold the profile. Your constructor should look like this:
+
+ ```javascript
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ person: {
+ name() {
+ return 'Anonymous';
+ },
+ avatarUrl() {
+ return avatarFallbackImage;
+ },
+ },
+ username: "",
+ newStatus: "",
+ statuses: [],
+ statusIndex: 0,
+ isLoading: false
+ };
+ }
+ ```
+
+
+4. Locate the `render()` method.
+5. Modify the `render()` method to add a text input and submit button to the application.
+
+ The following code echos the `person.name` and `person.avatarURL`
+ properties from the profile on the display:
+
+ ```javascript
+ render() {
+ const { handleSignOut } = this.props;
+ const { person } = this.state;
+ const { username } = this.state;
+
+ return (
+ !isSignInPending() && person ?
+
: null
+ );
+ }
+ ```
+
+ This code allows the application to post statuses. It also displays the
+ user's Blockstack ID. To display this, your app must extract the ID from the
+ user profile data.
+
+6. Locate the `componentWillMount()` method.
+7. Add the `username` property below the `person` property.
+
+ You'll use the Blockstack `loadUserData()` method to access the `username`.
+
+
+ ```javascript
+ componentWillMount() {
+ this.setState({
+ person: new Person(loadUserData().profile),
+ username: loadUserData().username
+ });
+ }
+ ```
+
+7. Add two methods to handle the status input events:
+
+ ```javascript
+ handleNewStatusChange(event) {
+ this.setState({newStatus: event.target.value})
+ }
+
+ handleNewStatusSubmit(event) {
+ this.saveNewStatus(this.state.newStatus)
+ this.setState({
+ newStatus: ""
+ })
+ }
+ ```
+
+8. Add a `saveNewStatus()` method to save the new statuses.
+
+ ```javascript
+ saveNewStatus(statusText) {
+ let statuses = this.state.statuses
+
+ let status = {
+ id: this.state.statusIndex++,
+ text: statusText.trim(),
+ created_at: Date.now()
+ }
+
+ statuses.unshift(status)
+ const options = { encrypt: false }
+ putFile('statuses.json', JSON.stringify(statuses), options)
+ .then(() => {
+ this.setState({
+ statuses: statuses
+ })
+ })
+ }
+ ```
+
+9. Save the `Profile.jsk` file.
+
+ After the application compiles successfully, your application should appears as follows:
+
+ ![](images/display-complete.png)
+
+10. Enter your status in the text box and press the **Submit** button.
+
+ At this point, nothing is blogged. In the next section you add code to display
+ the statuses back to the user as a blog entry.
+
+## Fetch and display statuses
+
+Update `Profile.jsx` again.
+
+1. Go back to the `render()` method.
+2. Locate the `
` containing the text input and **Submit** button.
+3. Right after this opening `div` element, add this block.
+
+ ```javascript
+
+ ```
+ This loads existing state. Your code needs to fetch statuses on page load.
+
+4. Add a new method called `fetchData()` after the `statuses.unshift(status)` section.
+
+ ```javascript
+
+ fetchData() {
+ this.setState({ isLoading: true })
+ const options = { decrypt: false }
+ getFile('statuses.json', options)
+ .then((file) => {
+ var statuses = JSON.parse(file || '[]')
+ this.setState({
+ person: new Person(loadUserData().profile),
+ username: loadUserData().username,
+ statusIndex: statuses.length,
+ statuses: statuses,
+ })
+ })
+ .finally(() => {
+ this.setState({ isLoading: false })
+ })
+ }
+ ```
+
+5. Call `fetchData()` from the `componentDidMount()` method
+
+ ```javascript
+
+ componentDidMount() {
+ this.fetchData()
+ }
+ ```
+
+6. Save the file.
+
+ After the application compiles successfully, users are able to **Submit**
+ multiple statuses and review them in the app.
+
+ ![](images/saving-status.png)
+
+## Change the style
+
+1. Edit the `src/styles/style.css` file.
+2. Replace the content with the following:
+
+
+ ```css
+ /* Globals */
+ a,a:focus,a:hover{color:#fff;}
+ html,body{height:100%;text-align:center;background-color:#191b22;}
+ body{color:#fff}
+ .hide{display:none;}
+ .landing-heading{font-family:'Lato',Sans-Serif;font-weight:400;}
+
+ /* Buttons */
+ .btn{font-family:'Lato',Sans-Serif;padding:0.5625rem 2.5rem;font-size:0.8125rem;font-weight:400;line-height:1.75rem;border-radius:0!important;-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;-ms-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;}
+ .btn-lg{font-size:1.5rem;padding:0.6875rem 3.4375rem;line-height:2.5rem;}
+ .btn:focus,.btn:active:focus,.btn.active:focus{outline:none;}
+ .btn-primary{color:#fff;border:1px solid #2C96FF;background-color:#2C96FF;}
+ .btn-primary:hover,.btn-primary:focus,.btn-primary:active{color:#fff;border:1px solid #1a6ec0;background-color:#1a6ec0;}
+
+ /* Avatar */
+ .avatar{width:100px;height:100px;}
+ .avatar-section{margin-bottom:25px;display:flex;text-align:left;}
+ .username{margin-left:20px;}
+
+ /* Scaffolding */
+ .site-wrapper{display:table;width:100%;height:100vh;min-height:100%;}
+ .site-wrapper-inner{display:flex;flex-direction:column;justify-content:center;margin-right:auto;margin-left:auto;width:100%;height:100vh;}
+ .panel-authed{padding:0 0 0 0;}
+
+ /* Home button */
+ .btn-home-hello{position:absolute;font-family:'Source Code Pro',monospace;font-size:11px;font-weight:400;color:rgba(255,255,255,0.85);top:15px;left:15px;padding:3px 20px;background-color:rgba(255,255,255,0.15);border-radius:6px;-webkit-box-shadow:0px 0px 20px 0px rgba(0,0,0,0.15);-moz-box-shadow:0px 0px 20px 0px rgba(0,0,0,0.15);box-shadow:0px 0px 20px 0px rgba(0,0,0,0.15);}
+
+ /* Input */
+ input, textarea{color:#000;padding:10px;}
+ .input-status{width:100%;height:70px;border-radius:6px;}
+ .new-status{text-align:right;}
+
+ /* Statuses */
+ .statuses{padding-top:30px;}
+ .status{margin:15px 0px;padding:20px;background-color:#2e2e2e;border-radius:6px}
+ ```
+
+3. Save and close the `src/styles/style.css` file.
+
+ After the application compiles, you should see the following:
+
+ ![Multi-reader storage authentication](images/multi-player-storage-status.png)
+
+
+At this point, you have a basic micro-blogging app that users can use to post and
+view statuses. However, there's no way to view other users' statuses. You'll add
+that in the next section.
+
+## Lookup user profiles
+
+Let's now modify the `Profile.jsx` file to display profiles of other users. You'll
+be using the `lookupProfile()` method that you added to the `import` statement
+earlier. `lookupProfile()` takes a single parameter that is the Blockstack ID of
+the profile and returns a profile object.
+
+### Add a new route
+
+Make some changes to the routing structure of your app so that users can view
+other users' profiles by visiting `http://localhost:8080/other_user.id`
+
+
+1. Make sure you are in the root of your `publik` project.
+2. Install `react-router`:
+
+ ```bash
+ npm install --save react-router-dom
+ ```
+
+3. Edit `src/index.js` file.
+4. Add an `import` to the file at the top:
+
+ ```javascript
+ import { BrowserRouter } from 'react-router-dom'
+ ```
+
+5. Change the `ReactDOM.render()` method in `src/index.js` to:
+
+ ```javascript
+ ReactDOM.render((
+
+
+
+ ), document.getElementById('root'));
+ ```
+6. Save and close the `src/index.js` file.
+7. Edit the `src/components/App.jsx` file.
+8. Add the new route by importing the `Switch` and `Route` components from `react-router-dom`:
+
+ ```javascript
+ import { Switch, Route } from 'react-router-dom'
+ ```
+9. Locate this line below in the `render()` method:
+
+ ```javascript
+ :
+ ```
+
+10. Replace it with the following:
+
+ ```javascript
+ :
+
+
+ }
+ />
+
+ ```
+
+ This sets up a route and captures the route parameter the app will use as the profile lookup username.
+
+11. Save and close the the `src/components/App.jsx` file.
+
+
+### Add a rule to process URL paths with . (dot)
+
+You also need to add a rule to your webpack config so that you can properly
+process URL paths that contain the `.` (dot) character for example,
+`http://localhost:8080/other_user.id`
+
+**NOTE**: In a production app, you must ensure the web server is configured to handle this.
+
+
+1. Open `webpack.config.js` in the root project directory and locate the following line:
+
+ ```javascript
+ historyApiFallback: true,
+ ```
+
+2. Replace it with this:
+
+ ```javascript
+ historyApiFallback: {
+ disableDotRule: true
+ },
+ ```
+
+ You will need to run `npm start` again for this change to take effect. Don't
+ worry, there is a later step for that to remind you.
+
+3. Save and close the `webpack.config.js` file.
+
+4. Edit the `src/components/Profile.jsx` file.
+5. Add a single method that determines if the app is viewing the local user's profile or another user's profile.
+
+ ```javascript
+ isLocal() {
+ return this.props.match.params.username ? false : true
+ }
+ ```
+
+ You use `isLocal()` to check if the user is viewing the local user profile or another user's profile. If it's the local user profile, the app runs the `getFile()` function you added in an earlier step. Otherwise, the app looks up the profile belonging to the `username` using the `lookupProfile()` method.
+
+6. Modify the `fetchData()` method like so:
+
+ ```javascript
+ fetchData() {
+ this.setState({ isLoading: true })
+ if (this.isLocal()) {
+ const options = { decrypt: false }
+ getFile('statuses.json', options)
+ .then((file) => {
+ var statuses = JSON.parse(file || '[]')
+ this.setState({
+ person: new Person(loadUserData().profile),
+ username: loadUserData().username,
+ statusIndex: statuses.length,
+ statuses: statuses,
+ })
+ })
+ .finally(() => {
+ this.setState({ isLoading: false })
+ })
+ } else {
+ const username = this.props.match.params.username
+
+ lookupProfile(username)
+ .then((profile) => {
+ this.setState({
+ person: new Person(profile),
+ username: username
+ })
+ })
+ .catch((error) => {
+ console.log('could not resolve profile')
+ })
+ }
+ }
+ ```
+
+ **NOTE**: For `https` deployments, the default Blockstack Core API endpoint for name
+ lookups should be changed to point to a core API served over `https`.
+ Otherwise, name lookups fail due to browsers blocking mixed content.
+ Refer to the [Blockstack.js
+ documentation](http://blockstack.github.io/blockstack.js/#getfile) for
+ details.
+
+7. Add the following block to `fetchData()` right after the call to `lookupProfile(username)... catch((error)=>{..}` block:
+
+ ```javascript
+ const options = { username: username, decrypt: false }
+ getFile('statuses.json', options)
+ .then((file) => {
+ var statuses = JSON.parse(file || '[]')
+ this.setState({
+ statusIndex: statuses.length,
+ statuses: statuses
+ })
+ })
+ .catch((error) => {
+ console.log('could not fetch statuses')
+ })
+ .finally(() => {
+ this.setState({ isLoading: false })
+ })
+ ```
+
+ This fetches the user statuses.
+
+ Finally, you must conditionally render the logout button, status input textbox, and submit button so they don't show up when viewing another user's profile.
+
+8. Replace the `render()` method with the following:
+
+ ```javascript
+ render() {
+ const { handleSignOut } = this.props;
+ const { person } = this.state;
+ const { username } = this.state;
+
+ return (
+ !isSignInPending() && person ?
+
: null
+ );
+ }
+ ```
+
+ ### This checks to ensure that users are viewing their own profile, by wrapping the **Logout** button and inputs with the `{isLocal() && ...}` condition.
+
+### Put it all together
+
+1. Stop the running application by sending a CTL-C.
+2. Restart the application so that the disabling of the `.` (dot) rule takes effect.
+
+ ```bash
+ npm start
+ ```
+
+3. Point your browser to `http://localhost:8080/your_blockstack.id` to see the final application.
+
+
+
+## Wrapping up
+
+Congratulations, you are all done! We hope you've enjoyed learning a bit more
+about Blockstack. To use a working version of the app go
+[here](http://publik.ykliao.com).
diff --git a/_browser/.svn/pristine/66/6621d9feb3a2a15035193f6c0c393c822241ec8f.svn-base b/_browser/.svn/pristine/66/6621d9feb3a2a15035193f6c0c393c822241ec8f.svn-base
new file mode 100644
index 00000000..33ea78a6
--- /dev/null
+++ b/_browser/.svn/pristine/66/6621d9feb3a2a15035193f6c0c393c822241ec8f.svn-base
@@ -0,0 +1,210 @@
+---
+layout: usenew
+permalink: /:collection/:path.html
+---
+# Get and use a Blockstack ID
+{:.no_toc}
+
+Through the Blockstack browser you can create an identity. Your identity is a
+point of contact as you interact with others through Dapps. Others may be
+individual users or companies or software. Unless you allow it, none of these
+others have access to anything other than your identity label, for example
+`moxiegirl.id.blockstack`. To learn more about you, others must ask and you can
+choose to share -- or not.
+
+This document explains one type of identity, the Blockstack ID. You learn how to
+create them, as well as when and how to restore them. It contains the following sections:
+
+* TOC
+{:toc}
+
+
+## Understand Blockstack IDs
+
+Interacting within the decentralized internet requires that you have at least
+one identity, though you can create several. Your identity is created through a
+registrar. Blockstack maintains a registrar for creating identities that you
+can use to interact with distributed applications (Dapps).
+
+To use the Blockstack Browser or to develop a decentralized application you
+require a Blockstack ID, for example `moxiegirl.id.blockstack`. A Blockstack ID
+is a digital identity that is registered With Blockstack. Your personal data and
+storage are built around this ID. Decentralized applications that want to access
+your data need your identity and your permission.
+
+When you first sign up through the Blockstack browser, you create an initial
+human-readable identity in the `id.blockstack` domain. This initial identity has
+the format:
+
+_`USERNAME`_`.id.blockstack`
+
+The _`USERNAME`_ portion must be unique. You enter an email and password to
+create the initial identity. Blockstack uses the password to:
+
+ * seed a _recovery code_ an encrypted string, for example `36mWivFdy0YPH2z31EflpQz/Y0UMrOrJ++lH=0EI7c3mop2JuRBm5W1P0BwXxSTazJsUjOAmC55rFUWINqDqGccLio0iwzGclAhaHGZQ5M52`
+ * seed a _recovery key_ which is a squence of words `applied binge crisp pictorial fiery dancing agreeable frogs light finish ping apple`
+
+The email is provided to allow either Blockstack or a decentralized application
+to communicate information to you. In Blockstacks' case, the email is used to
+send you reovery information.
+
+While Blockstack registers your human readable ID and the recovery key. _You_ must
+record the:
+
+* recovery key
+* recovery code (in the order the words apepar)
+* initial password
+
+Blockstack does not store them, so it can't give them to you later if they are
+lost.
+
+Your initial ID is created in the `id.blockstack` domain. The initial identity
+remains primary, and you need this primary ID and its associated information
+(recovery code, recovery key, and password) to use the browser again.
+
+Finally, the `id.blockstack` domain is sponsored by the Blockstack registrar and
+identities on it are free. Once you are using the Blockstack Browser, you can
+create additional identities outside of this domain and controlled by other
+registrars. Coin is required to purchase identities on other domains.
+
+## Create an initial Blockstack ID
+
+To create an inititial Blockstack ID, do the following:
+
+1. Open the [Blockstack web application in your browser](https://browser.blockstack.org/sign-up?redirect=%2F).
+
+ The application prompts you for an email address.
+
+ ![](images/create-id-0.png)
+
+ Blockstack uses this email address to send you recovery information.
+
+2. Enter an email address and press **Next**.
+
+ The application prompts you to enter a password. Blockstack users this
+ password to encrypt your recovery code. You must record and save this
+ initial password.
+
+ **NOTE**:The Blockstack team cannot restore your password for you.
+
+3. Enter a password, confirm it, and press **Next**.
+
+ ![](images/create-id-1.png)
+
+ The browser prompts you to register a unique username in the `id.blockstack`
+ domain. This is your identity in the decentralized internet. The format of the id
+ is:
+
+ _`username`_`.id.blockstack`
+
+ You'll use this initial ID to access the Blockstack Browser.
+
+3. Enter a unique username and press **Check Availability**.
+
+ ![](images/create-id-2.png)
+
+ When you choose an ID that is available, the system responds with the following:
+
+ ![](images/create-id-3.png)
+
+4. Press **Continue**.
+
+ The system prompts you to save your **recovery code**. A recovery code is a
+ sequence of words. These words allow you to recover an `id.blockstack`
+ that you've created. You should store the words along with their order, for
+ example, `#1 applied` and so forth.
+
+5. Click **I have written down all the words** when you are done.
+
+ The system places you in the Blockstack browser. You can begin exploring and
+ using Dapps.
+
+## Restore a Blockstack ID
+
+When you return to the Blockstack Browser, the browser prompts you to create a
+new Blockstack ID or restore an existing Blockstack ID. If you have a
+Blockstack identity, you can open the browser by restoring the identity. To
+restore an identity, there are two available methods.
+
+Method 1: Supply the identity recovery code (`36mWivFdy0YPH2z31E...`) and the
+password you provided when you _initially_ created your identity. Method 2:
+Supply the recovery key which is a sequence of words (`applied binge ...`)
+
+If you loose either the recovery code or the password you provided when you
+_initially_ created your identity, you can no longer use method 1 to restore
+your identity. If you lose the recovery key, you can no longer use method 2.
+Once you no longer have access to either method, your identity is estranged and
+not accessible by anyone.
+
+### Restore with a recovery key
+
+1. Open the [Blockstack web application in your browser](https://browser.blockstack.org/sign-up?redirect=%2F).
+2. Choose **Restore a Blockstack ID**.
+
+ The system displays a dialog where you can enter your recovery code or a
+ recovery key.
+
+3. Enter the recovery key.
+
+ The recovery key is a squence of words.
+
+ ![](images/recovery-code.png)
+
+4. Press **Next**.
+
+ The system prompts you for an email address. This email can be one you
+ entered previously or an entirely new one. Blockstack doesn't store this
+ address; it is used during your current Blockstack browser interaction to communicate
+ important information with you.
+
+5. Enter an email and press **Next**.
+
+ The system prompts you for an password and its confirmation. This password
+ can be one you entered previously or an entirely new one. Write this password
+ down. You can use the password during your current Blockstack browser
+ interaction to reveal your keychain or change your password. Blockstack does
+ not store this information past the session.
+
+6. Enter a password and press **Next**.
+
+ The system welcomes you back.
+
+ ![](images/welcome-back.png)
+
+ At this point, you can go onto work with Dapps or you can review your recovery key.
+
+### Restore with a recovery code and original password
+
+1. Open the [Blockstack web application in your browser](https://browser.blockstack.org/sign-up?redirect=%2F).
+2. Choose **Restore a Blockstack ID**.
+
+ The system displays a dialog where you can enter your recovery code or a
+ recovery key.
+
+3. Enter your recovery code.
+
+ The recovery code is an encrypted string.
+
+ ![](images/recovery-code.png)
+
+4. Press **Next**.
+
+ The system prompts you for an email address. This email can be one you
+ entered previously or an entirely new one. Blockstack doesn't store this
+ address; it is used during your current Blockstack browser interaction to
+ communicate important information with you.
+
+5. Enter an email and press **Next**.
+
+ The system prompts you for an password. This must be the password entered
+ when you first created your identity. If you have forgetten this passowrd,
+ Blockstack cannot provide it to you. Instead, you must switch to using your
+ recovery key rather than your code to restore your identity.
+
+6. Enter your origin password and press **Next**.
+
+ The system welcomes you back.
+
+ ![](images/welcome-back.png)
+
+ At this point, you can go work with Dapps or you can review your recovery key.
diff --git a/_browser/.svn/pristine/6c/6cf236705739b3dc1eaa714fab9bace84b283e8b.svn-base b/_browser/.svn/pristine/6c/6cf236705739b3dc1eaa714fab9bace84b283e8b.svn-base
new file mode 100644
index 00000000..d080b559
Binary files /dev/null and b/_browser/.svn/pristine/6c/6cf236705739b3dc1eaa714fab9bace84b283e8b.svn-base differ
diff --git a/_browser/.svn/pristine/7d/7d026a516855c1ccedf5ee6a2fe63126d09c8e26.svn-base b/_browser/.svn/pristine/7d/7d026a516855c1ccedf5ee6a2fe63126d09c8e26.svn-base
new file mode 100644
index 00000000..e653b034
Binary files /dev/null and b/_browser/.svn/pristine/7d/7d026a516855c1ccedf5ee6a2fe63126d09c8e26.svn-base differ
diff --git a/_browser/.svn/pristine/7e/7e40e7b1ee5b4f12d441e53a6ab89e94ad1fca90.svn-base b/_browser/.svn/pristine/7e/7e40e7b1ee5b4f12d441e53a6ab89e94ad1fca90.svn-base
new file mode 100644
index 00000000..097ae3b0
Binary files /dev/null and b/_browser/.svn/pristine/7e/7e40e7b1ee5b4f12d441e53a6ab89e94ad1fca90.svn-base differ
diff --git a/_browser/.svn/pristine/85/85996c7ad7783aa09fc9583b4befe746d24be5e5.svn-base b/_browser/.svn/pristine/85/85996c7ad7783aa09fc9583b4befe746d24be5e5.svn-base
new file mode 100644
index 00000000..416d4bd8
Binary files /dev/null and b/_browser/.svn/pristine/85/85996c7ad7783aa09fc9583b4befe746d24be5e5.svn-base differ
diff --git a/_browser/.svn/pristine/88/880a628c402d072057a35178bbbc13b8437c46bb.svn-base b/_browser/.svn/pristine/88/880a628c402d072057a35178bbbc13b8437c46bb.svn-base
new file mode 100644
index 00000000..dd51ac7c
Binary files /dev/null and b/_browser/.svn/pristine/88/880a628c402d072057a35178bbbc13b8437c46bb.svn-base differ
diff --git a/_browser/.svn/pristine/89/8917230875187dc926ba9f5a9a86e781975585ad.svn-base b/_browser/.svn/pristine/89/8917230875187dc926ba9f5a9a86e781975585ad.svn-base
new file mode 100644
index 00000000..9a521f11
Binary files /dev/null and b/_browser/.svn/pristine/89/8917230875187dc926ba9f5a9a86e781975585ad.svn-base differ
diff --git a/_browser/.svn/pristine/8e/8e3163bec841bf2fb8cc6ecbbf49f02e64b1e2d8.svn-base b/_browser/.svn/pristine/8e/8e3163bec841bf2fb8cc6ecbbf49f02e64b1e2d8.svn-base
new file mode 100644
index 00000000..76f1331c
Binary files /dev/null and b/_browser/.svn/pristine/8e/8e3163bec841bf2fb8cc6ecbbf49f02e64b1e2d8.svn-base differ
diff --git a/_browser/.svn/pristine/94/9400d6428e2bb287e9c7385bedb6ee563f5829d0.svn-base b/_browser/.svn/pristine/94/9400d6428e2bb287e9c7385bedb6ee563f5829d0.svn-base
new file mode 100644
index 00000000..9c932f51
Binary files /dev/null and b/_browser/.svn/pristine/94/9400d6428e2bb287e9c7385bedb6ee563f5829d0.svn-base differ
diff --git a/_browser/.svn/pristine/a3/a388e8949737a271d80b69b8dfcf48d77dddb890.svn-base b/_browser/.svn/pristine/a3/a388e8949737a271d80b69b8dfcf48d77dddb890.svn-base
new file mode 100644
index 00000000..f0eb285c
Binary files /dev/null and b/_browser/.svn/pristine/a3/a388e8949737a271d80b69b8dfcf48d77dddb890.svn-base differ
diff --git a/_browser/.svn/pristine/a8/a8348770072ebc93d3d6669efb8fb2225bbb39de.svn-base b/_browser/.svn/pristine/a8/a8348770072ebc93d3d6669efb8fb2225bbb39de.svn-base
new file mode 100644
index 00000000..1e7a2fb2
Binary files /dev/null and b/_browser/.svn/pristine/a8/a8348770072ebc93d3d6669efb8fb2225bbb39de.svn-base differ
diff --git a/_browser/.svn/pristine/b0/b0150507ba3e8a583e83ad2c29256231c8b58373.svn-base b/_browser/.svn/pristine/b0/b0150507ba3e8a583e83ad2c29256231c8b58373.svn-base
new file mode 100644
index 00000000..fd962ff9
Binary files /dev/null and b/_browser/.svn/pristine/b0/b0150507ba3e8a583e83ad2c29256231c8b58373.svn-base differ
diff --git a/_browser/.svn/pristine/b7/b719720c84e885f3d96f0c0b14534214d6683f18.svn-base b/_browser/.svn/pristine/b7/b719720c84e885f3d96f0c0b14534214d6683f18.svn-base
new file mode 100644
index 00000000..6ff75ed5
Binary files /dev/null and b/_browser/.svn/pristine/b7/b719720c84e885f3d96f0c0b14534214d6683f18.svn-base differ
diff --git a/_browser/.svn/pristine/b9/b974564d6e487b3c718c87a3c3fa821b4ac3d833.svn-base b/_browser/.svn/pristine/b9/b974564d6e487b3c718c87a3c3fa821b4ac3d833.svn-base
new file mode 100644
index 00000000..ab31536d
Binary files /dev/null and b/_browser/.svn/pristine/b9/b974564d6e487b3c718c87a3c3fa821b4ac3d833.svn-base differ
diff --git a/_browser/.svn/pristine/bf/bfa77ea6b63530fb7273cc51c462f37d9479a75b.svn-base b/_browser/.svn/pristine/bf/bfa77ea6b63530fb7273cc51c462f37d9479a75b.svn-base
new file mode 100644
index 00000000..4dca5dd1
Binary files /dev/null and b/_browser/.svn/pristine/bf/bfa77ea6b63530fb7273cc51c462f37d9479a75b.svn-base differ
diff --git a/_browser/.svn/pristine/ca/ca6de58cdaf847ead67cc9893c73b040cdd6fb08.svn-base b/_browser/.svn/pristine/ca/ca6de58cdaf847ead67cc9893c73b040cdd6fb08.svn-base
new file mode 100644
index 00000000..38054d90
Binary files /dev/null and b/_browser/.svn/pristine/ca/ca6de58cdaf847ead67cc9893c73b040cdd6fb08.svn-base differ
diff --git a/_browser/.svn/pristine/cf/cfe2a40e44a14cf0e7be26fed8c2430dc0d259e2.svn-base b/_browser/.svn/pristine/cf/cfe2a40e44a14cf0e7be26fed8c2430dc0d259e2.svn-base
new file mode 100644
index 00000000..4db24d43
--- /dev/null
+++ b/_browser/.svn/pristine/cf/cfe2a40e44a14cf0e7be26fed8c2430dc0d259e2.svn-base
@@ -0,0 +1,80 @@
+---
+layout: usenew
+permalink: /:collection/:path.html
+---
+# Users Frequently Asked Questions (FAQ)
+{:.no_toc}
+
+This is a general FAQ intended for users of decentralized applications. If you are a developer, refer to the [technical FAQ].
+
+* TOC
+{:toc}
+
+
+## What is the decentralized internet?
+
+The Blockstack ecosystem enables the new decentralized internet. Decentralization means authority moving from central authority to local authority. Simply put, in a decentralized interent, you your data, not the applications or services you use.
+
+Blockstack envisions a world where users control their own data, and power flows back to the users. For example, when you buy something from an online company, that company collects and stores data about you:
+
+* your name
+* the information about the product you bought
+* the number on your credit card
+
+In the decentralied internet, that information stays with you and it isn't
+collected or stored by anyone. Applications that operate in the decentralized
+internet are called _decentralized applications_ or Dapps for short.
+
+## What is Blockstack?
+
+Blockstack is an ecosystem to support both Dapp users and Dapp developers. For
+users, Blockstack makes software to create Blockstack identities and find Dapps.
+For developers, Blockstack develops an ecosystem of software and services that developrs can use to build Dapps.
+
+Blockstack through its
+
+## How do Dapps differ applications I typically use?
+
+Dapps differ from Web applications in two ways:
+
+* **Users have identities not accounts**. The user brings their identity to the
+ applications; applications do not require the user to create accounts and
+passwords.
+* **Users own their data**. Users control access to their data. Users decide where to store their data and which applications can read or write to your. Companies and their decentralized applications don't keep or save your data.
+
+
+## Where is my identity kept?
+
+Your identity is a unique string you and other people can read such as `moxiegirl.id`. A private key is a string of letters only you know. When you create an identity, a **hash** is made of your id and your private key registered with Blockstack.
+
+Your personal data storage is built around this ID. Apps that want to access your data use your permission and identity to find it.
+
+You have to remember and keep your private key in a safe place like a password manager. If you lose a private key, _no one else, no person, no software, can help you get your identity back_.
+
+## Can Blockstack control my data or ID when I use it?
+
+No. When you're using a Blockstack client you control your data and ID with a
+private key. As long as no one gets access to your private key, no one can
+control your data or ID. When you use Blockstack, by design, your private keys
+are never sent to any remote servers.
+
+## Do Dapps uwork with a regular browser?
+
+Yes! Dapps run in the web browsers (Chrome, Safari, Internet Explorer, etc.) you know and love.
+
+## What is the Blockstack Browser?
+
+The Blockstack Browser is the Dapp users use to create and manage their identities and configure their data storage. The browser is also where users can go to discover and use apps using Blockstack.
+
+The Blockstack Browser also handles login requests from Dapps that allow their users to log in with Blockstack. When a user clicks a **Log In with Blockstack** button, they are redirected to the Blockstack Browser to approve the request before being logged into the app.
+
+
+## Are Blockstack applications usable today?
+
+Yes! Blockstack applications are as easy to use as normal Web applications, if
+not easier. Moreover, they are just as performant if not more so.
+
+If you install the [Blockstack
+Browser](https://github.com/blockstack/blockstack-browser), or use our
+[Web-hosted Blockstack Browser](https://browser.blockstack.org), you can get
+started with them right away.
diff --git a/_browser/.svn/pristine/d0/d085d6df138e87cfea31a57a1e732327fbe01244.svn-base b/_browser/.svn/pristine/d0/d085d6df138e87cfea31a57a1e732327fbe01244.svn-base
new file mode 100644
index 00000000..8d42ed23
Binary files /dev/null and b/_browser/.svn/pristine/d0/d085d6df138e87cfea31a57a1e732327fbe01244.svn-base differ
diff --git a/_browser/.svn/pristine/d6/d6e6a8f19612c2353e5ff02ac49dc06762f7127c.svn-base b/_browser/.svn/pristine/d6/d6e6a8f19612c2353e5ff02ac49dc06762f7127c.svn-base
new file mode 100644
index 00000000..80ccff9a
Binary files /dev/null and b/_browser/.svn/pristine/d6/d6e6a8f19612c2353e5ff02ac49dc06762f7127c.svn-base differ
diff --git a/_browser/.svn/pristine/db/db11f02ca2f4fd6473c082112db7fd86c19d2039.svn-base b/_browser/.svn/pristine/db/db11f02ca2f4fd6473c082112db7fd86c19d2039.svn-base
new file mode 100644
index 00000000..4db7a650
Binary files /dev/null and b/_browser/.svn/pristine/db/db11f02ca2f4fd6473c082112db7fd86c19d2039.svn-base differ
diff --git a/_browser/.svn/pristine/eb/ebb5e5f52918709d42ea6cbba0df6b008039e281.svn-base b/_browser/.svn/pristine/eb/ebb5e5f52918709d42ea6cbba0df6b008039e281.svn-base
new file mode 100644
index 00000000..d708342e
Binary files /dev/null and b/_browser/.svn/pristine/eb/ebb5e5f52918709d42ea6cbba0df6b008039e281.svn-base differ
diff --git a/_browser/.svn/pristine/ec/ec3db3fa698c68b7eb55535729ca0bf5306d33ba.svn-base b/_browser/.svn/pristine/ec/ec3db3fa698c68b7eb55535729ca0bf5306d33ba.svn-base
new file mode 100644
index 00000000..8bada23b
Binary files /dev/null and b/_browser/.svn/pristine/ec/ec3db3fa698c68b7eb55535729ca0bf5306d33ba.svn-base differ
diff --git a/_browser/.svn/pristine/f1/f110c7b263eda5b8f71f1426dd9829625a5b1b31.svn-base b/_browser/.svn/pristine/f1/f110c7b263eda5b8f71f1426dd9829625a5b1b31.svn-base
new file mode 100644
index 00000000..4b3d4a5f
Binary files /dev/null and b/_browser/.svn/pristine/f1/f110c7b263eda5b8f71f1426dd9829625a5b1b31.svn-base differ
diff --git a/_browser/.svn/pristine/f2/f2da2a06b1ae6cece6cb9389f80dd5bb11cd7a98.svn-base b/_browser/.svn/pristine/f2/f2da2a06b1ae6cece6cb9389f80dd5bb11cd7a98.svn-base
new file mode 100644
index 00000000..5aa06112
Binary files /dev/null and b/_browser/.svn/pristine/f2/f2da2a06b1ae6cece6cb9389f80dd5bb11cd7a98.svn-base differ
diff --git a/_browser/.svn/pristine/f7/f7d8196207101d3fd6bf9efa91cb074dcbea011d.svn-base b/_browser/.svn/pristine/f7/f7d8196207101d3fd6bf9efa91cb074dcbea011d.svn-base
new file mode 100644
index 00000000..ddd6367f
Binary files /dev/null and b/_browser/.svn/pristine/f7/f7d8196207101d3fd6bf9efa91cb074dcbea011d.svn-base differ
diff --git a/_browser/.svn/pristine/fe/feb47456df368ff71ac8c50b94702abec6bf2619.svn-base b/_browser/.svn/pristine/fe/feb47456df368ff71ac8c50b94702abec6bf2619.svn-base
new file mode 100644
index 00000000..a3228716
Binary files /dev/null and b/_browser/.svn/pristine/fe/feb47456df368ff71ac8c50b94702abec6bf2619.svn-base differ
diff --git a/_browser/.svn/pristine/ff/ff4ec7f9dcc8b70af2d527b508b30c47a5386514.svn-base b/_browser/.svn/pristine/ff/ff4ec7f9dcc8b70af2d527b508b30c47a5386514.svn-base
new file mode 100644
index 00000000..992ef584
Binary files /dev/null and b/_browser/.svn/pristine/ff/ff4ec7f9dcc8b70af2d527b508b30c47a5386514.svn-base differ
diff --git a/_browser/.svn/wc.db b/_browser/.svn/wc.db
new file mode 100644
index 00000000..2e1f7fed
Binary files /dev/null and b/_browser/.svn/wc.db differ
diff --git a/_browser/.svn/wc.db-journal b/_browser/.svn/wc.db-journal
new file mode 100644
index 00000000..e69de29b
diff --git a/_browser/README.md b/_browser/README.md
new file mode 100644
index 00000000..787392e1
--- /dev/null
+++ b/_browser/README.md
@@ -0,0 +1,27 @@
+# Tutorials
+
+**Note: This data is being digested by blockstack.org. Do not change the formatting of this list unless you first make an adjustment to the code on blockstack.org.**
+
+### Multi-player Storage
+
+- urlSlug: multi-player-storage
+- image: /images/tutorials/multi-player-storage.png
+- description: Build a decentralized micro-blogging app using multi-player Gaia storage.
+
+### Managing Data with Gaia
+
+- urlSlug: managing-data-with-gaia
+- image: /images/tutorials/managing-data-with-gaia.png
+- description: This series will focus on teaching you to think like a Blockstack developer working with Gaia.
+
+### Blockstack Todo
+
+- urlSlug: todo-list
+- image: /images/tutorials/todo-list.png
+- description: Walk through creating a basic Todo application with Blockstack. Learn about Sign In flow and Gaia storage.
+
+### Hello Blockstack
+
+- urlSlug: hello-blockstack
+- image: /images/tutorials/hello-blockstack.jpg
+- description: Build a simple single-page JavaScript application that runs completely client-side without any servers.
diff --git a/_browser/blockstack_storage.md b/_browser/blockstack_storage.md
new file mode 100644
index 00000000..aa417c5f
--- /dev/null
+++ b/_browser/blockstack_storage.md
@@ -0,0 +1,812 @@
+---
+layout: learn
+permalink: /:collection/:path.html
+---
+# Blockstack Storage Tutorial
+{:.no_toc}
+
+In this tutorial, you build a micro-blogging application using multi-player Gaia
+storage. Gaia is Blockstack's [decentralized high-performance storage
+system](https://github.com/blockstack/gaia). The tutorial contains the following
+topics:
+
+* TOC
+{:toc}
+
+This tutorial does not teach you about authentication. That is covered in depth [in the hello-blockstack tutorial](hello-blockstack).
+
+
+
+
+{% include note.html content="This tutorial was written on macOS High Sierra 10.13.4. If you use a Windows or Linux system, you can still follow along. However, you will need to \"translate\" appropriately for your operating system. Additionally, this tutorial assumes you are accessing the Blockstack Browser web application via Chrome. The application you build will also work with a local installation and/or with browsers other than Chrome. " %}
+
+## About this tutorial and the prerequisites you need
+
+The storage application you build with this tutorial is a React.js application
+that is completely decentralized and server-less. While not strictly required
+to follow along, basic familiarity with React.js is helpful.
+
+When complete, the app is capable of the following:
+
+- authenticating users using Blockstack
+- posting new statuses
+- displaying statuses in the user profile
+- looking up the profiles and statuses of other users
+
+The basic identity and storage services are provided by `blockstack.js`. To test
+the application, you need to have already [registered a Blockstack ID](ids-introduction).
+
+The tutorial relies on the `npm` dependency manager. Before you begin, verify
+you have installed `npm` using the `which` command.
+
+```bash
+$ which npm
+/usr/local/bin/npm
+```
+
+If you don't find `npm` in your system, [install
+it](https://www.npmjs.com/get-npm). Finally, if you get stuck at any point
+while working on the tutorial, the completed [source code is available for
+you](https://github.com/larrysalibra/publik) to check your work against.
+
+## Use npm to install Yeoman and the Blockstack App Generator
+
+You use `npm` to install Yeoman. Yeoman is a generic scaffolding system that
+helps users rapidly start new projects and streamline the maintenance of
+existing projects.
+
+
+1. Install Yeoman.
+
+ ```bash
+ npm install -g yo
+ ```
+2. Install the Blockstack application generator.
+
+ ```bash
+ npm install -g generator-blockstack
+ ```
+
+
+
+## Generate and launch the public application
+
+In this section, you build an initial React.js application called Publik.
+
+1. Create a the `publik` directory.
+
+ ```bash
+ mkdir publik
+ ```
+
+2. Change into your new directory.
+
+ ```bash
+ cd publik
+ ```
+
+3. Use Yeoman and the Blockstack application generator to create your initial `publik` application.
+
+ ```bash
+ yo blockstack:react
+ ```
+
+ You should see several interactive prompts.
+
+ ```bash
+ $ yo blockstack:react
+ ? ==========================================================================
+ We're constantly looking for ways to make yo better!
+ May we anonymously report usage statistics to improve the tool over time?
+ More info: https://github.com/yeoman/insight & http://yeoman.io
+ ========================================================================== No
+
+ _-----_ ╭──────────────────────────╮
+ | | │ Welcome to the │
+ |--(o)--| │ Blockstack app │
+ `---------´ │ generator! │
+ ( _´U`_ ) ╰──────────────────────────╯
+ /___A___\ /
+ | ~ |
+ __'.___.'__
+ ´ ` |° ´ Y `
+
+ ? Are you ready to build a Blockstack app in React? (Y/n)
+ ```
+
+4. Respond to the prompts to populate the initial app.
+
+ After the process completes successfully, you see a prompt similar to the following:
+
+ ```bash
+ [fsevents] Success:
+ "/Users/theuser/repos/publik/node_modules/fsevents/lib/binding/Release/node-v59-darwin-x64/fse.node"
+ is installed via remote npm notice created a lockfile as package-lock.json.
+ You should commit this file. added 1060 packages in 26.901s
+ ```
+
+5. Run the initial application.
+
+ ```bash
+ npm start
+ ```
+
+ The system prompts you to accept incoming connections.
+
+ ![Network Connection](./images/network-connections.gif)
+
+6. Choose **Allow**.
+
+7. Open your browser to `http://localhost:8080`.
+
+ You should see a simple React app.
+
+ ![](images/initial-app.gif)
+
+8. Choose **Sign In with Blockstack**.
+
+ The application tells you it will **Read your basic info**.
+
+ ![](images/login.png)
+
+Leave your new application running and move onto the next section.
+
+## Add the `publish_data` scope to sign in requests
+
+Every app that uses Gaia storage must add itself to the user's `profile.json`
+file. The Blockstack browser does this automatically when the `publish_data`
+scope is requested during authentication. For this application, the user files
+stored on Gaia are made visible to others via the `apps` property in the user's
+`profile.json` file.
+
+Modify your authentication request to include the `publish_data` scope.
+
+1. Open `src/components/App.jsx` file.
+
+2. Locate the `handleSignIn` handler method.
+
+ ```javascript
+ handleSignIn(e) {
+ e.preventDefault();
+ redirectToSignIn();
+ }
+ ```
+
+2. Modify the method to this:
+
+ ```javascript
+ handleSignIn(e) {
+ e.preventDefault();
+ const origin = window.location.origin
+ redirectToSignIn(origin, origin + '/manifest.json', ['store_write', 'publish_data'])
+ }
+ ```
+
+ By default, authentication requests include the `store_write` scope which
+ enables storage. This is what allows you to store information to Gaia.
+
+3. Save your changes.
+4. Go back to your app at `http://localhost:8080/`.
+5. Log out and sign in again.
+
+ The authentication request now prompts the user for permission to **Publish
+ data stored for the app**.
+
+ ![](images/publish-data-perm.png)
+
+## Understand Gaia storage methods
+
+Once you authenticate a user with `store_write` and `publish_data`, you can
+begin to manage data for your users. Blockstack JS provides two methods
+`getFile()` and `putFile()` for interacting with Gaia storage. The storage
+methods support all file types. This means you can store SQL, Markdown, JSON, or
+even a custom format.
+
+You can create a meaningful and complex data layer using these two methods.
+Before creating an application, consider fundamental data architecture and make
+some decisions about how you’re modeling data. For example, consider building a
+simple grocery list app. A user should be able to create, read, update, and
+delete grocery lists.
+
+A single file collection stores items as an array nested inside each grocery
+list:
+
+```js
+// grocerylists.json
+{
+ "3255": {
+ "items": [
+ "1 Head of Lettuce",
+ "Haralson apples"
+ ]
+ },
+ // ...more lists with items
+}
+```
+
+This is conceptually the simplest way to manage grocery lists. When you read a
+`/grocerylists.json` file with `getFile()`, you get back one or more grocery
+lists and their items. When you write a single list, the `putFile()` method
+overwrites the entire list. So, a write operation for a new or updated grocery
+list must submit all existings lists as well.
+
+Further, because this runs on the client where anything can go wrong. If the
+client-side code encounters a parsing error with a user-input value and you
+could overwrite the entire file with:
+
+`line 6: Parsing Error: Unexpected token.`
+
+Further, a single file makes pagination impossible and if your app stores a
+single file for all list you have less control over file permissions. To avoid
+these issues, you can create an index file that stores an array of IDs. These
+IDs point to a name of another file in a `grocerylists` folder.
+
+![](images/multiple-lists.png)
+
+This design allows you to get only the files you need and avoid accidentally
+overwriting all lists. Further, you’re only updating the index file when you add
+or remove a grocery list; updating a list has no impact.
+
+
+## Add support for user status submission and lookup
+
+In this step, you add three `blockstack.js` methods that support posting of "statuses". These are the `putFile()`, `getFile()`, and `lookupProfile()` methods.
+
+1. Open the `src/components/Profile.jsx` file.
+
+2. Expand the `import from blockstack` statement with data methods.
+
+ The `Person` object holds a Blockstack profile. Add `putFile`, `getFile`,
+ and `lookupProfile` after `Person`.
+
+ When you are done, the import statement should look like the following:
+
+ ```javascript
+ import {
+ isSignInPending,
+ loadUserData,
+ Person,
+ getFile,
+ putFile,
+ lookupProfile
+ } from 'blockstack';
+ ```
+
+3. Replace the `constructor()` initial state so that it holds the key properties required by the app.
+
+ This code constructs a Blockstack `Person` object to hold the profile. Your constructor should look like this:
+
+ ```javascript
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ person: {
+ name() {
+ return 'Anonymous';
+ },
+ avatarUrl() {
+ return avatarFallbackImage;
+ },
+ },
+ username: "",
+ newStatus: "",
+ statuses: [],
+ statusIndex: 0,
+ isLoading: false
+ };
+ }
+ ```
+
+
+4. Locate the `render()` method.
+5. Modify the `render()` method to add a text input and submit button to the application.
+
+ The following code echos the `person.name` and `person.avatarURL`
+ properties from the profile on the display:
+
+ ```javascript
+ render() {
+ const { handleSignOut } = this.props;
+ const { person } = this.state;
+ const { username } = this.state;
+
+ return (
+ !isSignInPending() && person ?
+
: null
+ );
+ }
+ ```
+
+ This code allows the application to post statuses. It also displays the
+ user's Blockstack ID. To display this, your app must extract the ID from the
+ user profile data.
+
+6. Locate the `componentWillMount()` method.
+7. Add the `username` property below the `person` property.
+
+ You'll use the Blockstack `loadUserData()` method to access the `username`.
+
+
+ ```javascript
+ componentWillMount() {
+ this.setState({
+ person: new Person(loadUserData().profile),
+ username: loadUserData().username
+ });
+ }
+ ```
+
+7. Add two methods to handle the status input events:
+
+ ```javascript
+ handleNewStatusChange(event) {
+ this.setState({newStatus: event.target.value})
+ }
+
+ handleNewStatusSubmit(event) {
+ this.saveNewStatus(this.state.newStatus)
+ this.setState({
+ newStatus: ""
+ })
+ }
+ ```
+
+8. Add a `saveNewStatus()` method to save the new statuses.
+
+ ```javascript
+ saveNewStatus(statusText) {
+ let statuses = this.state.statuses
+
+ let status = {
+ id: this.state.statusIndex++,
+ text: statusText.trim(),
+ created_at: Date.now()
+ }
+
+ statuses.unshift(status)
+ const options = { encrypt: false }
+ putFile('statuses.json', JSON.stringify(statuses), options)
+ .then(() => {
+ this.setState({
+ statuses: statuses
+ })
+ })
+ }
+ ```
+
+9. Save the `Profile.jsk` file.
+
+ After the application compiles successfully, your application should appears as follows:
+
+ ![](images/display-complete.png)
+
+10. Enter your status in the text box and press the **Submit** button.
+
+ At this point, nothing is blogged. In the next section you add code to display
+ the statuses back to the user as a blog entry.
+
+## Fetch and display statuses
+
+Update `Profile.jsx` again.
+
+1. Go back to the `render()` method.
+2. Locate the `
` containing the text input and **Submit** button.
+3. Right after this opening `div` element, add this block.
+
+ ```javascript
+
+ ```
+ This loads existing state. Your code needs to fetch statuses on page load.
+
+4. Add a new method called `fetchData()` after the `statuses.unshift(status)` section.
+
+ ```javascript
+
+ fetchData() {
+ this.setState({ isLoading: true })
+ const options = { decrypt: false }
+ getFile('statuses.json', options)
+ .then((file) => {
+ var statuses = JSON.parse(file || '[]')
+ this.setState({
+ person: new Person(loadUserData().profile),
+ username: loadUserData().username,
+ statusIndex: statuses.length,
+ statuses: statuses,
+ })
+ })
+ .finally(() => {
+ this.setState({ isLoading: false })
+ })
+ }
+ ```
+
+5. Call `fetchData()` from the `componentDidMount()` method
+
+ ```javascript
+
+ componentDidMount() {
+ this.fetchData()
+ }
+ ```
+
+6. Save the file.
+
+ After the application compiles successfully, users are able to **Submit**
+ multiple statuses and review them in the app.
+
+ ![](images/saving-status.png)
+
+## Change the style
+
+1. Edit the `src/styles/style.css` file.
+2. Replace the content with the following:
+
+
+ ```css
+ /* Globals */
+ a,a:focus,a:hover{color:#fff;}
+ html,body{height:100%;text-align:center;background-color:#191b22;}
+ body{color:#fff}
+ .hide{display:none;}
+ .landing-heading{font-family:'Lato',Sans-Serif;font-weight:400;}
+
+ /* Buttons */
+ .btn{font-family:'Lato',Sans-Serif;padding:0.5625rem 2.5rem;font-size:0.8125rem;font-weight:400;line-height:1.75rem;border-radius:0!important;-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;-ms-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;}
+ .btn-lg{font-size:1.5rem;padding:0.6875rem 3.4375rem;line-height:2.5rem;}
+ .btn:focus,.btn:active:focus,.btn.active:focus{outline:none;}
+ .btn-primary{color:#fff;border:1px solid #2C96FF;background-color:#2C96FF;}
+ .btn-primary:hover,.btn-primary:focus,.btn-primary:active{color:#fff;border:1px solid #1a6ec0;background-color:#1a6ec0;}
+
+ /* Avatar */
+ .avatar{width:100px;height:100px;}
+ .avatar-section{margin-bottom:25px;display:flex;text-align:left;}
+ .username{margin-left:20px;}
+
+ /* Scaffolding */
+ .site-wrapper{display:table;width:100%;height:100vh;min-height:100%;}
+ .site-wrapper-inner{display:flex;flex-direction:column;justify-content:center;margin-right:auto;margin-left:auto;width:100%;height:100vh;}
+ .panel-authed{padding:0 0 0 0;}
+
+ /* Home button */
+ .btn-home-hello{position:absolute;font-family:'Source Code Pro',monospace;font-size:11px;font-weight:400;color:rgba(255,255,255,0.85);top:15px;left:15px;padding:3px 20px;background-color:rgba(255,255,255,0.15);border-radius:6px;-webkit-box-shadow:0px 0px 20px 0px rgba(0,0,0,0.15);-moz-box-shadow:0px 0px 20px 0px rgba(0,0,0,0.15);box-shadow:0px 0px 20px 0px rgba(0,0,0,0.15);}
+
+ /* Input */
+ input, textarea{color:#000;padding:10px;}
+ .input-status{width:100%;height:70px;border-radius:6px;}
+ .new-status{text-align:right;}
+
+ /* Statuses */
+ .statuses{padding-top:30px;}
+ .status{margin:15px 0px;padding:20px;background-color:#2e2e2e;border-radius:6px}
+ ```
+
+3. Save and close the `src/styles/style.css` file.
+
+ After the application compiles, you should see the following:
+
+ ![Multi-reader storage authentication](images/multi-player-storage-status.png)
+
+
+At this point, you have a basic micro-blogging app that users can use to post and
+view statuses. However, there's no way to view other users' statuses. You'll add
+that in the next section.
+
+## Lookup user profiles
+
+Let's now modify the `Profile.jsx` file to display profiles of other users. You'll
+be using the `lookupProfile()` method that you added to the `import` statement
+earlier. `lookupProfile()` takes a single parameter that is the Blockstack ID of
+the profile and returns a profile object.
+
+### Add a new route
+
+Make some changes to the routing structure of your app so that users can view
+other users' profiles by visiting `http://localhost:8080/other_user.id`
+
+
+1. Make sure you are in the root of your `publik` project.
+2. Install `react-router`:
+
+ ```bash
+ npm install --save react-router-dom
+ ```
+
+3. Edit `src/index.js` file.
+4. Add an `import` to the file at the top:
+
+ ```javascript
+ import { BrowserRouter } from 'react-router-dom'
+ ```
+
+5. Change the `ReactDOM.render()` method in `src/index.js` to:
+
+ ```javascript
+ ReactDOM.render((
+
+
+
+ ), document.getElementById('root'));
+ ```
+6. Save and close the `src/index.js` file.
+7. Edit the `src/components/App.jsx` file.
+8. Add the new route by importing the `Switch` and `Route` components from `react-router-dom`:
+
+ ```javascript
+ import { Switch, Route } from 'react-router-dom'
+ ```
+9. Locate this line below in the `render()` method:
+
+ ```javascript
+ :
+ ```
+
+10. Replace it with the following:
+
+ ```javascript
+ :
+
+
+ }
+ />
+
+ ```
+
+ This sets up a route and captures the route parameter the app will use as the profile lookup username.
+
+11. Save and close the the `src/components/App.jsx` file.
+
+
+### Add a rule to process URL paths with . (dot)
+
+You also need to add a rule to your webpack config so that you can properly
+process URL paths that contain the `.` (dot) character for example,
+`http://localhost:8080/other_user.id`
+
+**NOTE**: In a production app, you must ensure the web server is configured to handle this.
+
+
+1. Open `webpack.config.js` in the root project directory and locate the following line:
+
+ ```javascript
+ historyApiFallback: true,
+ ```
+
+2. Replace it with this:
+
+ ```javascript
+ historyApiFallback: {
+ disableDotRule: true
+ },
+ ```
+
+ You will need to run `npm start` again for this change to take effect. Don't
+ worry, there is a later step for that to remind you.
+
+3. Save and close the `webpack.config.js` file.
+
+4. Edit the `src/components/Profile.jsx` file.
+5. Add a single method that determines if the app is viewing the local user's profile or another user's profile.
+
+ ```javascript
+ isLocal() {
+ return this.props.match.params.username ? false : true
+ }
+ ```
+
+ You use `isLocal()` to check if the user is viewing the local user profile or another user's profile. If it's the local user profile, the app runs the `getFile()` function you added in an earlier step. Otherwise, the app looks up the profile belonging to the `username` using the `lookupProfile()` method.
+
+6. Modify the `fetchData()` method like so:
+
+ ```javascript
+ fetchData() {
+ this.setState({ isLoading: true })
+ if (this.isLocal()) {
+ const options = { decrypt: false }
+ getFile('statuses.json', options)
+ .then((file) => {
+ var statuses = JSON.parse(file || '[]')
+ this.setState({
+ person: new Person(loadUserData().profile),
+ username: loadUserData().username,
+ statusIndex: statuses.length,
+ statuses: statuses,
+ })
+ })
+ .finally(() => {
+ this.setState({ isLoading: false })
+ })
+ } else {
+ const username = this.props.match.params.username
+
+ lookupProfile(username)
+ .then((profile) => {
+ this.setState({
+ person: new Person(profile),
+ username: username
+ })
+ })
+ .catch((error) => {
+ console.log('could not resolve profile')
+ })
+ }
+ }
+ ```
+
+ **NOTE**: For `https` deployments, the default Blockstack Core API endpoint for name
+ lookups should be changed to point to a core API served over `https`.
+ Otherwise, name lookups fail due to browsers blocking mixed content.
+ Refer to the [Blockstack.js
+ documentation](http://blockstack.github.io/blockstack.js/#getfile) for
+ details.
+
+7. Add the following block to `fetchData()` right after the call to `lookupProfile(username)... catch((error)=>{..}` block:
+
+ ```javascript
+ const options = { username: username, decrypt: false }
+ getFile('statuses.json', options)
+ .then((file) => {
+ var statuses = JSON.parse(file || '[]')
+ this.setState({
+ statusIndex: statuses.length,
+ statuses: statuses
+ })
+ })
+ .catch((error) => {
+ console.log('could not fetch statuses')
+ })
+ .finally(() => {
+ this.setState({ isLoading: false })
+ })
+ ```
+
+ This fetches the user statuses.
+
+ Finally, you must conditionally render the logout button, status input textbox, and submit button so they don't show up when viewing another user's profile.
+
+8. Replace the `render()` method with the following:
+
+ ```javascript
+ render() {
+ const { handleSignOut } = this.props;
+ const { person } = this.state;
+ const { username } = this.state;
+
+ return (
+ !isSignInPending() && person ?
+
: null
+ );
+ }
+ ```
+
+ ### This checks to ensure that users are viewing their own profile, by wrapping the **Logout** button and inputs with the `{isLocal() && ...}` condition.
+
+### Put it all together
+
+1. Stop the running application by sending a CTL-C.
+2. Restart the application so that the disabling of the `.` (dot) rule takes effect.
+
+ ```bash
+ npm start
+ ```
+
+3. Point your browser to `http://localhost:8080/your_blockstack.id` to see the final application.
+
+
+
+## Wrapping up
+
+Congratulations, you are all done! We hope you've enjoyed learning a bit more
+about Blockstack. To use a working version of the app go
+[here](http://publik.ykliao.com).
diff --git a/_browser/browser-introduction.md b/_browser/browser-introduction.md
new file mode 100644
index 00000000..a5f73e17
--- /dev/null
+++ b/_browser/browser-introduction.md
@@ -0,0 +1,86 @@
+---
+layout: usenew
+permalink: /:collection/:path.html
+---
+# Introduction to the Blockstack Browser
+
+{:.no_toc}
+
+The Blockstack Browser gives users the ability to explore and use the
+decentralized applications (Dapps). Dapps are a new way to interact with the
+internet. Dapps give users control of their data. Data about them personally,
+name, birthdate, phone number and data about what they do such as visiting a
+website or buying an item.
+
+* TOC
+{:toc}
+
+
+## Understand the Blockstack Browser
+
+Through the Blockstack browser application you can create an identity. An identity
+represents you as you interact with others through Dapps. The Blockstack
+Browser is itself, a simple Dapp. It allows you to:
+
+* create one or more identities
+* send and receive bitcoin
+* manage the storage of your profile and application data
+* find and launch Dapps
+
+There are two editions of the Blockstack Browser, the web edition is an
+application you access through your web browser by simply visiting the application's
+address in your computer's browser. You can also install the browser as a
+client application on your computer.
+
+If all you want to do is create, manage, and fund an identity and then interact
+with Dapps, you can simply use the web edition. If you have concerns about net
+censorship, heightened security concerns, or want to develop a Dapp yourself, you may
+want to download and install the browser's client edition.
+
+To use the web application to create an identity,
+
+## Using the Browser on public computers
+
+Before you use the web application, it is important to note that once you log
+into the application with the brower, your session does not expire until you
+choose **Settings > RESET BROWSER**. For this reason, you should be careful
+when using the browser on public computers.
+
+If you are in a library, for example, and log into the browser, simply
+closing the tab or even rebooting the computer does not log you out. Instead,
+you should be sure to choose **Settings > RESET BROWSER** before leaving the web
+application.
+
+For more informatin about your identity and the browser, see [Get and use a Blockstack ID](ids-introduction).
+
+## Overview of the browser functions
+
+The Blockstack Browser allows you to use the new internet. Toward this end, the Browser navigation has the following areas:
+
+![](images/navigation-top.png)
+
+
+
+
Item
+
Purpose
+
+
+
+
Home
+
Takes you to the initial page. This page contains a list of the available applications. You can also find available applications at the App.co site.
+
+
+
IDs
+
Allows you to establish the identity of your primary ID. You also go here to create additional, sub identities.
+
+
+
Wallet
+
Allows you to send and receive Bitcoin.
+
+
+
Settings
+
Configure settings for storage, change session password, reset the Browser, and more.
+
+
+
diff --git a/_browser/browser-nav.md b/_browser/browser-nav.md
new file mode 100644
index 00000000..f20db1e4
--- /dev/null
+++ b/_browser/browser-nav.md
@@ -0,0 +1,17 @@
+---
+layout: usenew
+permalink: /:collection/:path.html
+---
+
+
+On this page, you learn more about working with **IDs**, the **Wallet**, and **Settings**.
+
+## Working with IDS
+
+Blockstack allows you to create one free identity in the Blockstack
+_namespace_. A namespace a top-level category in the Blockstack Ecosystem. A
+namespace is similar to the domains you are familiar with from using the web,
+`google.com` is domain and so is the `gouvernement.fr` domain. An identity in
+the `.blockstack` namespace has the _`username`_`.id.blockstack` format.
+
+You can also purchase your own identity (`.id`) using bitcoin (BTC). A name's price depends on its length in characters and the current Bitcoin fees. For example, ranges such as .00831 and .001943 BTC 20-80 US dollars is not unusual.
diff --git a/_browser/faq_general.md b/_browser/faq_general.md
new file mode 100644
index 00000000..4db24d43
--- /dev/null
+++ b/_browser/faq_general.md
@@ -0,0 +1,80 @@
+---
+layout: usenew
+permalink: /:collection/:path.html
+---
+# Users Frequently Asked Questions (FAQ)
+{:.no_toc}
+
+This is a general FAQ intended for users of decentralized applications. If you are a developer, refer to the [technical FAQ].
+
+* TOC
+{:toc}
+
+
+## What is the decentralized internet?
+
+The Blockstack ecosystem enables the new decentralized internet. Decentralization means authority moving from central authority to local authority. Simply put, in a decentralized interent, you your data, not the applications or services you use.
+
+Blockstack envisions a world where users control their own data, and power flows back to the users. For example, when you buy something from an online company, that company collects and stores data about you:
+
+* your name
+* the information about the product you bought
+* the number on your credit card
+
+In the decentralied internet, that information stays with you and it isn't
+collected or stored by anyone. Applications that operate in the decentralized
+internet are called _decentralized applications_ or Dapps for short.
+
+## What is Blockstack?
+
+Blockstack is an ecosystem to support both Dapp users and Dapp developers. For
+users, Blockstack makes software to create Blockstack identities and find Dapps.
+For developers, Blockstack develops an ecosystem of software and services that developrs can use to build Dapps.
+
+Blockstack through its
+
+## How do Dapps differ applications I typically use?
+
+Dapps differ from Web applications in two ways:
+
+* **Users have identities not accounts**. The user brings their identity to the
+ applications; applications do not require the user to create accounts and
+passwords.
+* **Users own their data**. Users control access to their data. Users decide where to store their data and which applications can read or write to your. Companies and their decentralized applications don't keep or save your data.
+
+
+## Where is my identity kept?
+
+Your identity is a unique string you and other people can read such as `moxiegirl.id`. A private key is a string of letters only you know. When you create an identity, a **hash** is made of your id and your private key registered with Blockstack.
+
+Your personal data storage is built around this ID. Apps that want to access your data use your permission and identity to find it.
+
+You have to remember and keep your private key in a safe place like a password manager. If you lose a private key, _no one else, no person, no software, can help you get your identity back_.
+
+## Can Blockstack control my data or ID when I use it?
+
+No. When you're using a Blockstack client you control your data and ID with a
+private key. As long as no one gets access to your private key, no one can
+control your data or ID. When you use Blockstack, by design, your private keys
+are never sent to any remote servers.
+
+## Do Dapps uwork with a regular browser?
+
+Yes! Dapps run in the web browsers (Chrome, Safari, Internet Explorer, etc.) you know and love.
+
+## What is the Blockstack Browser?
+
+The Blockstack Browser is the Dapp users use to create and manage their identities and configure their data storage. The browser is also where users can go to discover and use apps using Blockstack.
+
+The Blockstack Browser also handles login requests from Dapps that allow their users to log in with Blockstack. When a user clicks a **Log In with Blockstack** button, they are redirected to the Blockstack Browser to approve the request before being logged into the app.
+
+
+## Are Blockstack applications usable today?
+
+Yes! Blockstack applications are as easy to use as normal Web applications, if
+not easier. Moreover, they are just as performant if not more so.
+
+If you install the [Blockstack
+Browser](https://github.com/blockstack/blockstack-browser), or use our
+[Web-hosted Blockstack Browser](https://browser.blockstack.org), you can get
+started with them right away.
diff --git a/_browser/hello-blockstack.md b/_browser/hello-blockstack.md
new file mode 100644
index 00000000..1ca66aac
--- /dev/null
+++ b/_browser/hello-blockstack.md
@@ -0,0 +1,330 @@
+---
+layout: learn
+permalink: /:collection/:path.html
+---
+# Hello, Blockstack Tutorial
+
+In this tutorial, you generate a simple application on Blockstack. The application
+is a single-page application (SPA) that runs completely client-side. The
+application has no backend API to talk to, other than the identity and storage
+API that the user provides. In this sense, the application is a completely
+decentralized, server-less application. You work through the following sections:
+
+* TOC
+{:toc}
+
+{% include note.html content="This tutorial was written on macOS High Sierra 10.13.4. If you use a Windows or Linux system, you can still follow along. However, you will need to \"translate\" appropriately for your operating system. Additionally, this tutorial assumes you are accessing the Blockstack Browser web application via Chrome. The application you build will also work with a local installation and/or with browsers other than Chrome. " %}
+
+## About this tutorial and the prerequisites you need
+
+For this tutorial, we will use the following tools:
+
+- `npm` to manage dependencies and scripts
+- `browserify` to compile node code into browser-ready code
+- `blockstack.js` to authenticate the user and work with the user's identity/profile information
+
+The application you build is a React.js application that is completely
+decentralized and server-less. While not strictly required to follow along,
+basic familiarity with React.js is helpful.
+
+When complete, the app is capable of the following:
+
+- authenticating users using Blockstack
+- posting new statuses
+- displaying statuses in the user profile
+- looking up the profiles and statuses of other users
+
+The basic identity and storage services are provided by `blockstack.js`. To test
+the application, you need to have already registered a Blockstack ID.
+
+The tutorial relies on the `npm` dependency manager. Before you begin, verify
+you have installed `npm` using the `which` command to verify.
+
+```bash
+$ which npm
+/usr/local/bin/npm
+```
+
+If you don't find `npm` in your system, [install
+it](https://www.npmjs.com/get-npm).
+
+Finally, make sure you have [created at least one Blockstack ID]({{ site.baseurl }}/browser/ids-introduction.html#create-an-initial-blockstack-id). You'll use this ID to interat with the application.
+
+## Use npm to install Yeoman and the Blockstack App Generator
+
+You use `npm` to install Yeoman. Yeoman is a generic scaffolding system that
+helps users rapidly start new projects and streamline the maintenance of
+existing projects.
+
+
+1. Install Yeoman.
+
+ ```bash
+ npm install -g yo
+ ```
+2. Install the Blockstack application generator.
+
+ ```bash
+ npm install -g generator-blockstack
+ ```
+
+## Generate an initial Blockstack application
+
+In this section, you build an initial React.js application called `hello-world-tutorial`.
+
+1. Create the `hello-world-tutorial` directory.
+
+ ```bash
+ mkdir hello-world-tutorial
+ ```
+
+2. Change into your new directory.
+
+ ```bash
+ cd hello-world-tutorial
+ ```
+
+3. Use Yeoman and the Blockstack application generator to create your initial `hello-world-tutorial` application.
+
+ ```bash
+ yo blockstack
+ ```
+
+ You should see several interactive prompts.
+
+ ```bash
+ $ yo blockstack
+
+ _-----_ ╭──────────────────────────╮
+ | | │ Welcome to the │
+ |--(o)--| │ Blockstack app │
+ `---------´ │ generator! │
+ ( _´U`_ ) ╰──────────────────────────╯
+ /___A___\ /
+ | ~ |
+ __'.___.'__
+ ´ ` |° ´ Y `
+
+ ? Are you ready to build a Blockstack app in React? (Y/n)
+ ```
+
+4. Respond to the prompts to populate the initial app.
+
+ After the process completes successfully, you see a prompt similar to the following:
+
+ ```bash
+ ...
+ create public/icon-192x192.png
+ create public/index.html
+ create public/robots.txt
+ create public/manifest.json
+
+
+ I'm all done. Running npm install for you to install the required dependencies. If this fails, try running the command yourself.
+ ```
+
+Depending on your environment you may have some problems with the `npm` packages. Go ahead and fix these before continuing to the next section.
+
+## Review the basic application structure
+
+The initial application you create is a generic Javascript application you run
+with a local express node. Before you continue, take a moment to examine the
+structure of this generic application structure:
+
+| File | Description |
+|------------------|-----------------------------------|
+| .editorconfig | Sets universal values for editor. |
+| .gitignore | Git configuration file. |
+| firebase.json | Configuragion for mobile application.|
+| package.json | Specifies required packages. |
+| requires.js | A Javascript module loader. |
+| server.js | Simple static server configuration.|
+
+In the `public` folder you find these files:
+
+| File | Description |
+|------------------|-----------------------------------|
+| app.css | Contains application styles. |
+| app.js | Main application file. |
+| boostrap.min.css | Minifield css for production. |
+| icon-192x192.png | Application icon |
+| index.html | Single page. |
+| manifest.json | Tells the browser about the application and how it should behave.|
+| robots.txt | Configures crawling and indexing. |
+
+The simple static file server in the `server.js`file serves all of the files in
+the `/public` directory, including `index.html`, `app.js`, `bootstrap.min.css`
+and `app.css`. The main file of the application is in the `app.js`. It contains
+the majority of the application logic.
+
+## Start the server and view the application
+
+When you start the server, it will create a Node.js server, start it locally,
+and open your browser 'http://localhost:5000'. From the root of your new application directory:
+
+1. Start the application server.
+
+ ```bash
+ npm start
+ ```
+
+ The first time you run it, your system prompts you to accept incoming connections.
+
+ ![Network Connection](images/network-connections.gif)
+
+2. Choose **Allow**.
+
+3. Open your browser to `http://localhost:8080`.
+
+ You should see a simple application:
+
+ ![](images/initial-app.gif)
+
+4. Choose **Sign In with Blockstack**.
+
+ The application detects whether the user has the Blockstack client edition installed or
+ not. This is done automatically by the Blockstack API, more about this later.
+ What the browser displays depends on the users' current state.
+
+ | Using web app | Has client edition installed |
+ |------------------|-----------------------------------|
+ | ![](images/login-choice.png) | ![](images/login.gif) |
+
+ If the user logged into the Blockstack Browser but not reset it, the user can
+ simply use the exiting identity.
+
+ ![](images/login-no-auth.png)
+
+ If the user chooses **Deny**, the Blockstack Browser displays its
+ **Home** page but the user is not logged into the sample application.
+
+5. Leave your new application running and move onto the next section.
+
+## Understand the generated application code
+
+In this section, you look at the basic application generated with the `yo
+blockstack` command. The generated code contains simple authentication methods
+that allow a user to log into the browser. The main application code is located
+in the `public/app.css` file. Open this file now.
+
+All of the code in the file is wrapped in an event
+listener.
+
+```js
+document.addEventListener("DOMContentLoaded", function(event) {
+})
+```
+
+This listener that waits until the DOM content is loaded. Then, it creates an auth request and redirects the user to sign in:
+
+```js
+document.getElementById('signin-button').addEventListener('click', function() {
+ blockstack.redirectUserToSignIn()
+})
+```
+
+You can find the `redirectUserToSignIn()` function is part of the [Blockstack Javascript documentation](https://blockstack.github.io/blockstack.js/). There is also a sign out button handler. This handler deletes the local user data and signs the user out:
+
+```js
+document.getElementById('signout-button').addEventListener('click', function() {
+ blockstack.signUserOut(window.location.origin)
+})
+```
+
+The handlers are followed by a `showProfile()` function for showing the user's profile:
+
+```js
+function showProfile(profile) {
+ var person = new blockstack.Person(profile)
+ document.getElementById('heading-name').innerHTML = person.name() ? person.name() : "Nameless Person"
+ if(person.avatarUrl()) {
+ document.getElementById('avatar-image').setAttribute('src', person.avatarUrl())
+ }
+ document.getElementById('section-1').style.display = 'none'
+ document.getElementById('section-2').style.display = 'block'
+}
+```
+
+Each `getElementById()` function refers to elemments in the `index.html` file.
+
+Once a user is successfully signed in, there is logic for loading the user
+profile and displaying the application. As illustrated earlier, there are
+several states the user can be in:
+
+- The user is already signed in
+- The user has a pending sign in request
+- The user is signed out
+
+The application handles these situtations as followed:
+
+```js
+if (blockstack.isUserSignedIn()) {
+ var profile = blockstack.loadUserData().profile
+ showProfile(profile)
+} else if (blockstack.isSignInPending()) {
+ blockstack.handlePendingSignIn().then(function(userData) {
+ window.location = window.location.origin
+ })
+}
+```
+
+When the user is signed in, Blockstack loads the user data from local storage
+and displays the profile with the `showProfile()` function. When the user has a
+pending sign in request, the appplication signs the user in and redirects the
+user back to the home page.
+
+### Application manifest
+
+The application's `/public/manifest.json` file configures your app. The
+configurations dictate how the application is displayed in auth views and on
+user home screens. The contents are very simple:
+
+```json
+{
+ "name": "Hello, Blockstack",
+ "start_url": "localhost:5000",
+ "description": "A simple demo of Blockstack Auth",
+ "icons": [{
+ "src": "https://helloblockstack.com/icon-192x192.png",
+ "sizes": "192x192",
+ "type": "image/png"
+ }]
+}
+```
+
+Keep it as is or fill it in with new information that describes your app.
+
+### Save your application code
+
+Complete the tutorial by storing your app code on GitHub. Before you begin, make sure you have a GitHub account and have configured your environment to use it.
+
+1. Initialize the application code as a Git repo.
+
+ ```bash
+ git init
+ ```
+
+2. Add and commit all of the files:
+
+ ```bash
+ git add . && git commit -m "first commit"
+ ```
+
+3. In GitHub, create a `hello-blockstack` repository.
+
+4. Back in your termininal window, add a remote for GitHub.
+
+ Make sure to fill in your username:
+
+ ```bash
+ git remote add origin git@github.com:YOUR_USERNAME_HERE/hello-blockstack.git
+ ```
+
+5. Push your new code to the master branch of the remote repo:
+
+ ```
+ git push origin master
+ ```
+
+You're done! You just built your first Blockstack app and shipped the code.
+You're well on your way to becoming a Blockstack app legend.
diff --git a/_browser/ids-creating.md b/_browser/ids-creating.md
new file mode 100644
index 00000000..723c9bc7
--- /dev/null
+++ b/_browser/ids-creating.md
@@ -0,0 +1,41 @@
+---
+layout: usenew
+permalink: /:collection/:path.html
+---
+# Working with IDS
+
+Blockstack allows you to create one free identity in the Blockstack
+_namespace_. A namespace a top-level category in the Blockstack Ecosystem. A
+namespace is similar to the domains you are familiar with from using the web,
+`google.com` is domain and so is the `gouvernement.fr` domain. An identity in
+the `.blockstack` namespace has the _`username`_`.id.blockstack` format.
+
+You can also purchase your own identity (`.id`) using bitcoin (BTC). A name's
+price depends on its length in characters and the current Bitcoin fees. For
+example, ranges such as .00831 and .001943 BTC 20-80 US dollars is not
+unusual.
+
+
+## Create an ID
+
+To, create an id, do the following:
+
+1. Go to the Blockstack Web Browser.
+
+
+ You have Blockstack Browser installed: If you start from ADD USERNAME from IDs window, jump to 6.
+1/ You do not have the Blockstack Browser installed: go to https://explorer.blockstack.org/ 99
+2/ Search for your name typing “yourname.id” on the search box. If your .id is “free”, the response will be “Ooops ! The name yourname.id doesn’t exist.” or will show a owner “mnbhbu235j46ijnowejjybjb” with Expires field empty and just NAME_IMPORT, no NAME_REGISTRATION.
+3/ Install de Blockstack Browser, open an account, write by hand on a piece of paper and make two copies of mnemonic 12 words phrase, DO NOT KEEP IT IN THE COMPUTER, DO NOT UPLOAD IT TO THE CLOUD, DO NOT COPY IT IN THE CLIPBOARD.
+4/ Go to IDs
+5/ Click ADD USERNAME. (or MORE and CREATE NEW ID if you want more than one .id’s)
+6/ Try your selected name (without “.id”)
+7/ If available, check the price.
+(If you want to buy a name with your wallet empty the process is a little more complex because the transfer can take a long time and the process will seems frozen, so I recommend to supply your wallet before, go to step 8)
+8/ Click WALLET
+9/ Fund your wallet with the correct amount or more.
+10/ Wait until you see the bitcoin amount in your wallet. Sometimes bitcoin net can take a minute or one hour (or 5) to perform the transaction depending on the demand of network operations, in the following link you will see approx. the time it will take to complete the transaction based on your fee: https://bitcoinfees.earn.com/ 22
+10/ Back to ADD USERNAME
+11/ Write your name and click search.
+12/ Click BUY
+13/ The process takes one hour or six blocks, DO NOT TURN OFF the browser or the computer for two hours.
diff --git a/_browser/ids-introduction.md b/_browser/ids-introduction.md
new file mode 100644
index 00000000..8b2268e2
--- /dev/null
+++ b/_browser/ids-introduction.md
@@ -0,0 +1,222 @@
+---
+layout: usenew
+permalink: /:collection/:path.html
+---
+# Get and use a Blockstack ID
+{:.no_toc}
+
+Through the Blockstack browser you can create an identity. Your identity is a
+point of contact as you interact with others through Dapps. Others may be
+individual users or companies or software. Unless you allow it, none of these
+others have access to anything other than your identity label, for example
+`moxiegirl.id.blockstack`. To learn more about you, others must ask and you can
+choose to share -- or not.
+
+This document explains one type of identity, the Blockstack ID. You learn how to
+create them, as well as when and how to restore them. It contains the following sections:
+
+* TOC
+{:toc}
+
+
+## Understand Blockstack IDs
+
+Interacting within the decentralized internet requires that you have at least
+one identity, though you can create several. Your identity is created through a
+registrar. Blockstack maintains a registrar for creating identities that you
+can use to interact with distributed applications (Dapps).
+
+To use the Blockstack Browser or to develop a Dapp you
+require a Blockstack ID, for example `moxiegirl.id.blockstack`. A Blockstack ID
+is a digital identity that is registered With Blockstack. Think of the ID as a
+form of identification, like a drivers license, but this license identifies you
+on the virtual internet highway.
+
+
+Your personal data storage is linked to this ID. You use this ID to
+identify yourself to other users and to sign into applications. When you add a
+picture to a Dapp, the picture appears in the Dapp but the picture's bits and bytes
+are stored in your personal storage.
+
+
+When you log into another application with your ID, that application can ask for access to that storage and then use that picture. The application must ask you, it knows you by your ID, and
+
+ Decentralized applications that want to access your data need your
+identity and your permission.
+
+When you first sign up through the Blockstack browser, you create an initial
+human-readable identity in the `id.blockstack` domain. This initial identity has
+the format:
+
+_`USERNAME`_`.id.blockstack`
+
+The _`USERNAME`_ portion must be unique. You enter an email and password to
+create the initial identity. Blockstack uses the password to:
+
+ * seed a _recovery code_ an encrypted string, for example `36mWivFdy0YPH2z31EflpQz/Y0UMrOrJ++lH=0EI7c3mop2JuRBm5W1P0BwXxSTazJsUjOAmC55rFUWINqDqGccLio0iwzGclAhaHGZQ5M52`
+ * seed a _recovery key_ which is a squence of words `applied binge crisp pictorial fiery dancing agreeable frogs light finish ping apple`
+
+The email is provided to allow either Blockstack or a decentralized application
+to communicate information to you. In Blockstacks' case, the email is used to
+send you reovery information.
+
+While Blockstack registers your human readable ID and the recovery key. _You_ must
+record the:
+
+* recovery key
+* recovery code (in the order the words apepar)
+* initial password
+
+Blockstack does not store them, so it can't give them to you later if they are
+lost.
+
+Your initial ID is created in the `id.blockstack` domain. The initial identity
+remains primary, and you need this primary ID and its associated information
+(recovery code, recovery key, and password) to use the browser again.
+
+Finally, the `id.blockstack` domain is sponsored by the Blockstack registrar and
+identities on it are free. Once you are using the Blockstack Browser, you can
+create additional identities outside of this domain and controlled by other
+registrars. Coin is required to purchase identities on other domains.
+
+## Create an initial Blockstack ID
+
+To create an inititial Blockstack ID, do the following:
+
+1. Open the [Blockstack web application in your browser](https://browser.blockstack.org/sign-up?redirect=%2F).
+
+ The application prompts you for an email address.
+
+ ![](images/create-id-0.png)
+
+ Blockstack uses this email address to send you recovery information.
+
+2. Enter an email address and press **Next**.
+
+ The application prompts you to enter a password. Blockstack users this
+ password to encrypt your recovery code. You must record and save this
+ initial password.
+
+ **NOTE**:The Blockstack team cannot restore your password for you.
+
+3. Enter a password, confirm it, and press **Next**.
+
+ ![](images/create-id-1.png)
+
+ The browser prompts you to register a unique username in the `id.blockstack`
+ domain. This is your identity in the decentralized internet. The format of the id
+ is:
+
+ _`username`_`.id.blockstack`
+
+ You'll use this initial ID to access the Blockstack Browser.
+
+3. Enter a unique username and press **Check Availability**.
+
+ ![](images/create-id-2.png)
+
+ When you choose an ID that is available, the system responds with the following:
+
+ ![](images/create-id-3.png)
+
+4. Press **Continue**.
+
+ The system prompts you to save your **recovery code**. A recovery code is a
+ sequence of words. These words allow you to recover an `id.blockstack`
+ that you've created. You should store the words along with their order, for
+ example, `#1 applied` and so forth.
+
+5. Click **I have written down all the words** when you are done.
+
+ The system places you in the Blockstack browser. You can begin exploring and
+ using Dapps.
+
+## Restore a Blockstack ID
+
+When you return to the Blockstack Browser, the browser prompts you to create a
+new Blockstack ID or restore an existing Blockstack ID. If you have a
+Blockstack identity, you can open the browser by restoring the identity. To
+restore an identity, there are two available methods.
+
+Method 1: Supply the identity recovery code (`36mWivFdy0YPH2z31E...`) and the
+password you provided when you _initially_ created your identity. Method 2:
+Supply the recovery key which is a sequence of words (`applied binge ...`)
+
+If you loose either the recovery code or the password you provided when you
+_initially_ created your identity, you can no longer use method 1 to restore
+your identity. If you lose the recovery key, you can no longer use method 2.
+Once you no longer have access to either method, your identity is estranged and
+not accessible by anyone.
+
+### Restore with a recovery key
+
+1. Open the [Blockstack web application in your browser](https://browser.blockstack.org/sign-up?redirect=%2F).
+2. Choose **Restore a Blockstack ID**.
+
+ The system displays a dialog where you can enter your recovery code or a
+ recovery key.
+
+3. Enter the recovery key.
+
+ The recovery key is a squence of words.
+
+ ![](images/recovery-code.png)
+
+4. Press **Next**.
+
+ The system prompts you for an email address. This email can be one you
+ entered previously or an entirely new one. Blockstack doesn't store this
+ address; it is used during your current Blockstack browser interaction to communicate
+ important information with you.
+
+5. Enter an email and press **Next**.
+
+ The system prompts you for an password and its confirmation. This password
+ can be one you entered previously or an entirely new one. Write this password
+ down. You can use the password during your current Blockstack browser
+ interaction to reveal your keychain or change your password. Blockstack does
+ not store this information past the session.
+
+6. Enter a password and press **Next**.
+
+ The system welcomes you back.
+
+ ![](images/welcome-back.png)
+
+ At this point, you can go onto work with Dapps or you can review your recovery key.
+
+### Restore with a recovery code and original password
+
+1. Open the [Blockstack web application in your browser](https://browser.blockstack.org/sign-up?redirect=%2F).
+2. Choose **Restore a Blockstack ID**.
+
+ The system displays a dialog where you can enter your recovery code or a
+ recovery key.
+
+3. Enter your recovery code.
+
+ The recovery code is an encrypted string.
+
+ ![](images/recovery-code.png)
+
+4. Press **Next**.
+
+ The system prompts you for an email address. This email can be one you
+ entered previously or an entirely new one. Blockstack doesn't store this
+ address; it is used during your current Blockstack browser interaction to
+ communicate important information with you.
+
+5. Enter an email and press **Next**.
+
+ The system prompts you for an password. This must be the password entered
+ when you first created your identity. If you have forgetten this passowrd,
+ Blockstack cannot provide it to you. Instead, you must switch to using your
+ recovery key rather than your code to restore your identity.
+
+6. Enter your origin password and press **Next**.
+
+ The system welcomes you back.
+
+ ![](images/welcome-back.png)
+
+ At this point, you can go work with Dapps or you can review your recovery key.
diff --git a/_browser/images/blockstack-bar.png b/_browser/images/blockstack-bar.png
new file mode 100644
index 00000000..1d95fee1
Binary files /dev/null and b/_browser/images/blockstack-bar.png differ
diff --git a/_browser/images/browser-on-mac-1.png b/_browser/images/browser-on-mac-1.png
new file mode 100644
index 00000000..6ff75ed5
Binary files /dev/null and b/_browser/images/browser-on-mac-1.png differ
diff --git a/_browser/images/browser-on-mac.png b/_browser/images/browser-on-mac.png
new file mode 100644
index 00000000..5aa06112
Binary files /dev/null and b/_browser/images/browser-on-mac.png differ
diff --git a/_browser/images/browser-uninstall.png b/_browser/images/browser-uninstall.png
new file mode 100644
index 00000000..4b3d4a5f
Binary files /dev/null and b/_browser/images/browser-uninstall.png differ
diff --git a/_browser/images/create-id-0.png b/_browser/images/create-id-0.png
new file mode 100644
index 00000000..76f1331c
Binary files /dev/null and b/_browser/images/create-id-0.png differ
diff --git a/_browser/images/create-id-1.png b/_browser/images/create-id-1.png
new file mode 100644
index 00000000..bf6c096a
Binary files /dev/null and b/_browser/images/create-id-1.png differ
diff --git a/_browser/images/create-id-2.png b/_browser/images/create-id-2.png
new file mode 100644
index 00000000..006eeca5
Binary files /dev/null and b/_browser/images/create-id-2.png differ
diff --git a/_browser/images/create-id-3.png b/_browser/images/create-id-3.png
new file mode 100644
index 00000000..26d88672
Binary files /dev/null and b/_browser/images/create-id-3.png differ
diff --git a/_browser/images/display-complete.png b/_browser/images/display-complete.png
new file mode 100644
index 00000000..097ae3b0
Binary files /dev/null and b/_browser/images/display-complete.png differ
diff --git a/_browser/images/dmg-notice.png b/_browser/images/dmg-notice.png
new file mode 100644
index 00000000..f0eb285c
Binary files /dev/null and b/_browser/images/dmg-notice.png differ
diff --git a/_browser/images/eject-blockstack.png b/_browser/images/eject-blockstack.png
new file mode 100644
index 00000000..4db7a650
Binary files /dev/null and b/_browser/images/eject-blockstack.png differ
diff --git a/_browser/images/hw-loggedin.png b/_browser/images/hw-loggedin.png
new file mode 100644
index 00000000..829f7c1f
Binary files /dev/null and b/_browser/images/hw-loggedin.png differ
diff --git a/_browser/images/initial-app.gif b/_browser/images/initial-app.gif
new file mode 100644
index 00000000..9c932f51
Binary files /dev/null and b/_browser/images/initial-app.gif differ
diff --git a/_browser/images/login-choice.png b/_browser/images/login-choice.png
new file mode 100644
index 00000000..00bc6af3
Binary files /dev/null and b/_browser/images/login-choice.png differ
diff --git a/_browser/images/login-no-auth.png b/_browser/images/login-no-auth.png
new file mode 100644
index 00000000..8bada23b
Binary files /dev/null and b/_browser/images/login-no-auth.png differ
diff --git a/_browser/images/login.gif b/_browser/images/login.gif
new file mode 100644
index 00000000..c2626b50
Binary files /dev/null and b/_browser/images/login.gif differ
diff --git a/_browser/images/login.png b/_browser/images/login.png
new file mode 100644
index 00000000..80ccff9a
Binary files /dev/null and b/_browser/images/login.png differ
diff --git a/_browser/images/make-a-list.png b/_browser/images/make-a-list.png
new file mode 100644
index 00000000..8d42ed23
Binary files /dev/null and b/_browser/images/make-a-list.png differ
diff --git a/_browser/images/multi-player-storage-status.png b/_browser/images/multi-player-storage-status.png
new file mode 100644
index 00000000..fd962ff9
Binary files /dev/null and b/_browser/images/multi-player-storage-status.png differ
diff --git a/_browser/images/multiple-lists.png b/_browser/images/multiple-lists.png
new file mode 100644
index 00000000..a3228716
Binary files /dev/null and b/_browser/images/multiple-lists.png differ
diff --git a/_browser/images/navigation-top.png b/_browser/images/navigation-top.png
new file mode 100644
index 00000000..2b5bf9f0
Binary files /dev/null and b/_browser/images/navigation-top.png differ
diff --git a/_browser/images/network-connections.gif b/_browser/images/network-connections.gif
new file mode 100644
index 00000000..1e7a2fb2
Binary files /dev/null and b/_browser/images/network-connections.gif differ
diff --git a/_browser/images/new-prompt.gif b/_browser/images/new-prompt.gif
new file mode 100644
index 00000000..aa136ba1
Binary files /dev/null and b/_browser/images/new-prompt.gif differ
diff --git a/_browser/images/on-your-mind.gif b/_browser/images/on-your-mind.gif
new file mode 100644
index 00000000..d080b559
Binary files /dev/null and b/_browser/images/on-your-mind.gif differ
diff --git a/_browser/images/osx-dmg.png b/_browser/images/osx-dmg.png
new file mode 100644
index 00000000..019c67db
Binary files /dev/null and b/_browser/images/osx-dmg.png differ
diff --git a/_browser/images/publish-data-perm.png b/_browser/images/publish-data-perm.png
new file mode 100644
index 00000000..cd6b3b6a
Binary files /dev/null and b/_browser/images/publish-data-perm.png differ
diff --git a/_browser/images/quit-blockstack.png b/_browser/images/quit-blockstack.png
new file mode 100644
index 00000000..5352b913
Binary files /dev/null and b/_browser/images/quit-blockstack.png differ
diff --git a/_browser/images/recovery-code.png b/_browser/images/recovery-code.png
new file mode 100644
index 00000000..433ef3d5
Binary files /dev/null and b/_browser/images/recovery-code.png differ
diff --git a/_browser/images/sample-code.png b/_browser/images/sample-code.png
new file mode 100644
index 00000000..9fef9de2
Binary files /dev/null and b/_browser/images/sample-code.png differ
diff --git a/_browser/images/saving-status.png b/_browser/images/saving-status.png
new file mode 100644
index 00000000..ddd6367f
Binary files /dev/null and b/_browser/images/saving-status.png differ
diff --git a/_browser/images/status-in.gif b/_browser/images/status-in.gif
new file mode 100644
index 00000000..ab31536d
Binary files /dev/null and b/_browser/images/status-in.gif differ
diff --git a/_browser/images/todo-app.png b/_browser/images/todo-app.png
new file mode 100644
index 00000000..416d4bd8
Binary files /dev/null and b/_browser/images/todo-app.png differ
diff --git a/_browser/images/todo-sign-in.png b/_browser/images/todo-sign-in.png
new file mode 100644
index 00000000..9a521f11
Binary files /dev/null and b/_browser/images/todo-sign-in.png differ
diff --git a/_browser/images/ubuntu-browser.png b/_browser/images/ubuntu-browser.png
new file mode 100644
index 00000000..992ef584
Binary files /dev/null and b/_browser/images/ubuntu-browser.png differ
diff --git a/_browser/images/welcome-back.png b/_browser/images/welcome-back.png
new file mode 100644
index 00000000..38054d90
Binary files /dev/null and b/_browser/images/welcome-back.png differ
diff --git a/_browser/images/windows-apps-features.png b/_browser/images/windows-apps-features.png
new file mode 100644
index 00000000..d708342e
Binary files /dev/null and b/_browser/images/windows-apps-features.png differ
diff --git a/_browser/images/windows-browser.png b/_browser/images/windows-browser.png
new file mode 100644
index 00000000..d2c2dda2
Binary files /dev/null and b/_browser/images/windows-browser.png differ
diff --git a/_browser/images/windows-installer.png b/_browser/images/windows-installer.png
new file mode 100644
index 00000000..4dca5dd1
Binary files /dev/null and b/_browser/images/windows-installer.png differ
diff --git a/_browser/images/windows-security.png b/_browser/images/windows-security.png
new file mode 100644
index 00000000..e653b034
Binary files /dev/null and b/_browser/images/windows-security.png differ
diff --git a/_browser/images/windows-start.png b/_browser/images/windows-start.png
new file mode 100644
index 00000000..a5f0c27f
Binary files /dev/null and b/_browser/images/windows-start.png differ
diff --git a/_browser/local_browser.md b/_browser/local_browser.md
new file mode 100644
index 00000000..78c8b182
--- /dev/null
+++ b/_browser/local_browser.md
@@ -0,0 +1,252 @@
+---
+layout: usenew
+permalink: /:collection/:path.html
+---
+# Intall or uninstall the local browser
+{:.no_toc}
+
+If all you want to do is create, manage, and fund an identity and then interact
+with Dapps, you should [use the web edition](browser-introduction.html). If you
+have concerns about net censorship, heightened security concerns, or want to
+develop a Dapp yourself, you may want to download and install the browser's
+client edition; though it is not required. This page explains how to install or
+uninstall the browser client on a workstation.
+
+* TOC
+{:toc}
+
+## About the client install
+
+Remember, for most users the Blockstack Browser web application should
+suffice. You only need to install the client if you have additional, advanced
+concerns about Internet or identity. Though not required, some Dapp developrs
+may find it useful to install the client edition.
+
+The Blockstack Browser installer is a _multiple-context_ installer. If you
+run it as a user, the installation is avalable only for that user. If you
+install as administrator, the installation installs for all users. To find an
+installer for your operating system, visit the browser installation page.
+
+### On Mac
+
+Installation requires that you have macOS High Sierra 10.12 or higher. Do the following to install:
+
+1. Download the OSX installer from the browser installation page.
+2. Double-click the downloaded DMG file to launch the installer.
+
+ ![](images/ubuntu-browser.png)
+
+3. Drag the Blockstack.app to the `Applications` folder.
+4. Double-click the Blockstack.app to launch it.
+
+ The system displays a notice about opening the file:
+
+ ![](images/dmg-notice.png)
+
+5. Choose **Open**.
+
+ The system opens your default browser with the Blockstack Browser
+ application, running from your machine (localhost). You'll also see the
+ Blockstack icon in your machine's
+
+ ![](images/browser-on-mac.png)
+
+ If you have loaded an identity already via the Blockstack web application,
+ you are already logged into the local application:
+
+ ![](images/browser-on-mac-1.png)
+
+
+### On Windows
+
+Installation requires that you have Windows 10 or higher. Do the following to
+install:
+
+1. Download the Windows installer from from the browser installation page.
+2. Double-click the installer package to launch it.
+
+ ![](images/windows-installer.png)
+
+3. Open the Wiindows **Start** menu and click on the recently added **Blockstack Browser**.
+
+ ![](images/windows-start.png)
+
+ The system displays a Windows Security Alert.
+
+ ![](images/windows-security.png)
+
+4. Choose to **Allow access**.
+
+ The system opens in the Blockstack Browser application.
+
+ ![](images/windows-browser.png)
+
+
+### On Linux
+
+The Blockstack installation on Linux requires Docker. Before installing
+Blockstack, install the version of Docker appropriate for your operating system.
+
+>**Note**: The Blockstack script used in this procedure runs `docker` commands. Depending on how you installed and configure Dockered on your system, it may or may not be necessary to have `root` or `sudo` privileges. For this reason, the commands below show the use of `sudo` when interacting with the script or the `docker` executable. If your installation allows running Docker with lower privileges, you can omit it.
+
+
+1. Download the Linux installer from from the browser installation page.
+
+ This downloads a `Blockstack-for-Linux-v0.30.0.sh` script to your local drive.
+
+2. Open a terminal and navigate to the directory containing the downloaded script.
+
+ When the script downloads, it is not executable.
+
+3. Set the executable bit on the file.
+
+ ```bash
+ $ chmod u+x Blockstack-for-Linux-v0.309.0.0.sh
+ ```
+
+4. Enter the command without any arguments to see the available subcommands.
+
+ ```bash
+ $ sudo ./Blockstack-for-Linux-v0.309.0.0.sh
+ blockstack docker launcher commands:
+ Install-protocol-handler -> install a protocol handler for blockstack:// links
+ ...
+ ```
+
+5. Use the script to `pull` the Blockstack Docker images you need.
+
+
+ ```bash
+ $ sudo ./Blockstack-for-Linux-v0.309.0.0.sh pull
+ ```
+
+ Depending on your network speed, this can take some time.
+
+7. Use the `docker image ls` command to confirm you have the image.
+
+ ```bash
+ $ sudo docker image Is
+ REPOSITORY TAG IMAGE ID CREATED
+ quay.io/blockstack/blockstack-browser v0.30.0 ad05fd844f59 2 days ago
+ ```
+
+8. Install the protocol handler
+
+ ```bash
+ $ sudo ./Blockstack-for-Linux-vO.30.0.sh install-protocol-handler
+ Registering protocol handler
+ ```
+
+9. Start the Blockstack containers.
+
+ ```bash
+ $ sudo ./Blockstack-for-Linux-vO.30.0.sh start
+ c3092592e59abe3559fdb49d070a7aa5e99165c7d9f2flla20ecaf4e0dfc2f46
+ cd92f61ae473d54398da987f5023f5462b29c03f08584ebb3c9fIbb4cd790c69
+ Registering protocol handler
+ ```
+
+ The system launches the Blockstack Browser application for you.
+
+ ![](images/ubuntu-browser.png)
+
+Until you stop the Blockstack containers, the application will continue to run
+on your system. To display the status of the Blockstack containers, you can use
+the `docker container ls` command.
+
+{% raw %}
+```bash
+$ sudo docker container ls --format '{{.ID}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}\t{{.Names}}'
+```
+{% endraw %}
+
+Use `./Blockstack-for-Linux-vO.30.0.sh stop` to stop the Blockstack Browser and its containers.
+
+
+## Uninstall the browser
+
+If you installed the browser using an installer, follow the instructions for
+your operating system.
+
+### On Mac
+
+1. Quit the Blockstack application if it is running.
+
+ ![](images/quit-blockstack.png)
+
+2. Check if you have a Blockstack device and eject it if you do.
+
+ ![](images/eject-blockstack.png)
+
+3. Use the Finder to open the **Applications** folder.
+4. Locate the Blockstack application.
+5. Open your `Applications` folder and locate the **Blockstack.app**.
+6. Drag the appliation to the trash.
+7. Delete the `/Users/USERNAME/Library/Application Support/Blockstack` folder.
+
+ From the command line:
+
+ ```bash
+ $ rm -r /Users/moxiegirl/Library/Application\ Support/Blockstack
+ ```
+
+### On Windows
+
+1. Open the **Start** menu.
+2. Click **Settings > System**.
+3. Open for the **Apps & features** item.
+
+ ![](images/eject-blockstack.png)
+
+4. Locate the **Blockstack Browser** and choose **Uninstall**.
+
+ ![](images/browser-uninstall.png)
+
+
+### On Linux
+
+Your Blockstack instalaltion relies on Docker containers and their associated
+images. It also includes a supporting protocol handler you must remove. If you
+installed Docker so that you can run Blockstack, you can uninstall Docker as well,
+but that is not explained here.
+
+Do the following to uninstall Blockstack:
+
+1. Stop and remove the Docker containers if they are running.
+
+ ```bash
+ $ sudo ./Blockstack-for-Linux-vO.30.0.sh stop
+ stopping the running blockstack-browser containers
+ 69a686799d4f
+ 56fc6189ff97
+ 69a686799d4f
+ 56fc6189ff97
+ ```
+
+2. Remove the associated Blockstack images.
+
+ ```bash
+ $ sudo docker image ls
+ REPOSITORY TAG IMAGE ID CREATED
+ quay.io/blockstack/blockstack-browser v0.30.0 ad05fd844f59 3 days ago
+ $ sudo docker image rm ad05fd844f59
+ Untagged : quay.io/blockstack/blockstack- browser :vO.30.0
+ Untagged: quay.io/blockstack/blockstack-browser@sha256:b20c9514c56b99398fd4946af39e7537b807e85694943ac3b8807dlb3625833b
+ Deleted: Sha256:ad05fd844f5948blee06a0a09228df946478393c0a7588cbc65dlb8817f5b34e
+ Deleted: Sha256:7c3d0043f2ba01cf285f3fe09701b086c349b6380c2e42f25b31ac65c6626ec8
+ Deleted: sha256:54ea2aa7d7d000e7483f299eeca9e5466fa86231f4cd4cld3c3096d97e61c5df
+ Deleted: sha256:38e61054355adefc3c2de031462114a9946cfc0e44444a38a27d0f115aba0da2
+ ....
+ ```
+
+3. Use the script to remove the protocol handler
+
+ ```bash
+ $ sudo ./Blockstack-for-Linux-vO.30.0.sh remove-protocol-handler
+ ```
+
+4. Delete the script.
+
+ ```bash
+ $ rm Blockstack-for-Linux-vO.30.0.sh
+ ```
diff --git a/_browser/multi-player-storage.md b/_browser/multi-player-storage.md
new file mode 100644
index 00000000..ce4330d7
--- /dev/null
+++ b/_browser/multi-player-storage.md
@@ -0,0 +1,817 @@
+---
+layout: learn
+permalink: /:collection/:path.html
+---
+# Manage Data with Gaia
+{:.no_toc}
+
+In this tutorial, you build a micro-blogging application using multi-player Gaia
+storage. Gaia is Blockstack's [decentralized high-performance storage
+system](https://github.com/blockstack/gaia). The tutorial contains the following
+topics:
+
+* TOC
+{:toc}
+
+This tutorial does not teach you about authentication. That is covered in depth [in the hello-blockstack tutorial](hello-blockstack.html).
+
+
+
+
+
+## About this tutorial and the prerequisites you need
+
+{% include note.html content="This tutorial was written for a user running macOS. If you are running a Windows
+machine, you can still work through this tutorial. You will need to adjust the
+instructions for your environment."%}
+
+The application you build is a React.js application that is completely
+decentralized and server-less. While not strictly required to follow along,
+basic familiarity with React.js is helpful.
+
+When complete, the app is capable of the following:
+
+- authenticating users using Blockstack
+- posting new statuses
+- displaying statuses in the user profile
+- looking up the profiles and statuses of other users
+
+The basic identity and storage services are provided by `blockstack.js`. To test
+the application, you need to have already [registered a Blockstack ID](ids-introduction.html).
+
+The tutorial relies on the `npm` dependency manager. Before you begin, verify
+you have installed `npm` using the `which` command.
+
+```bash
+$ which npm
+/usr/local/bin/npm
+```
+
+If you don't find `npm` in your system, [install
+it](https://www.npmjs.com/get-npm). Finally, if you get stuck at any point
+while working on the tutorial, the completed [source code is available for
+you](https://github.com/larrysalibra/publik) to check your work against.
+
+High Sierra 10.13.4.
+
+## Use npm to install Yeoman and the Blockstack App Generator
+
+You use `npm` to install Yeoman. Yeoman is a generic scaffolding system that
+helps users rapidly start new projects and streamline the maintenance of
+existing projects.
+
+
+1. Install Yeoman.
+
+ ```bash
+ npm install -g yo
+ ```
+2. Install the Blockstack application generator.
+
+ ```bash
+ npm install -g generator-blockstack
+ ```
+
+
+
+## Generate and launch the public application
+
+In this section, you build an initial React.js application called Publik.
+
+1. Create a the `publik` directory.
+
+ ```bash
+ mkdir publik
+ ```
+
+2. Change into your new directory.
+
+ ```bash
+ cd publik
+ ```
+
+3. Use Yeoman and the Blockstack application generator to create your initial `publik` application.
+
+ ```bash
+ yo blockstack:react
+ ```
+
+ You should see several interactive prompts.
+
+ ```bash
+ $ yo blockstack:react
+ ? ==========================================================================
+ We're constantly looking for ways to make yo better!
+ May we anonymously report usage statistics to improve the tool over time?
+ More info: https://github.com/yeoman/insight & http://yeoman.io
+ ========================================================================== No
+
+ _-----_ ╭──────────────────────────╮
+ | | │ Welcome to the │
+ |--(o)--| │ Blockstack app │
+ `---------´ │ generator! │
+ ( _´U`_ ) ╰──────────────────────────╯
+ /___A___\ /
+ | ~ |
+ __'.___.'__
+ ´ ` |° ´ Y `
+
+ ? Are you ready to build a Blockstack app in React? (Y/n)
+ ```
+
+4. Respond to the prompts to populate the initial app.
+
+ After the process completes successfully, you see a prompt similar to the following:
+
+ ```bash
+ [fsevents] Success:
+ "/Users/theuser/repos/publik/node_modules/fsevents/lib/binding/Release/node-v59-darwin-x64/fse.node"
+ is installed via remote npm notice created a lockfile as package-lock.json.
+ You should commit this file. added 1060 packages in 26.901s
+ ```
+
+5. Run the initial application.
+
+ ```bash
+ npm start
+ ```
+
+ The system prompts you to accept incoming connections.
+
+ ![Network Connection](./images/network-connections.gif)
+
+6. Choose **Allow**.
+
+7. Open your browser to `http://localhost:8080`.
+
+ You should see a simple React app.
+
+ ![](images/initial-app.gif)
+
+8. Choose **Sign In with Blockstack**.
+
+ The application tells you it will **Read your basic info**.
+
+ ![](images/login.png)
+
+Leave your new application running and move onto the next section.
+
+## Add the `publish_data` scope to sign in requests
+
+Every app that uses Gaia storage must add itself to the user's `profile.json`
+file. The Blockstack browser does this automatically when the `publish_data`
+scope is requested during authentication. For this application, the user files
+stored on Gaia are made visible to others via the `apps` property in the user's
+`profile.json` file.
+
+Modify your authentication request to include the `publish_data` scope.
+
+1. Open `src/components/App.jsx` file.
+
+2. Locate the `handleSignIn` handler method.
+
+ ```javascript
+ handleSignIn(e) {
+ e.preventDefault();
+ redirectToSignIn();
+ }
+ ```
+
+2. Modify the method to this:
+
+ ```javascript
+ handleSignIn(e) {
+ e.preventDefault();
+ const origin = window.location.origin
+ redirectToSignIn(origin, origin + '/manifest.json', ['store_write', 'publish_data'])
+ }
+ ```
+
+ By default, authentication requests include the `store_write` scope which
+ enables storage. This is what allows you to store information to Gaia.
+
+3. Save your changes.
+4. Go back to your app at `http://localhost:8080/`.
+5. Log out and sign in again.
+
+ The authentication request now prompts the user for permission to **Publish
+ data stored for the app**.
+
+ ![](images/publish-data-perm.png)
+
+## Understand Gaia storage methods
+
+Once you authenticate a user with `store_write` and `publish_data`, you can
+begin to manage data for your users. Blockstack JS provides two methods
+`getFile()` and `putFile()` for interacting with Gaia storage. The storage
+methods support all file types. This means you can store SQL, Markdown, JSON, or
+even a custom format.
+
+You can create a meaningful and complex data layer using these two methods.
+Before creating an application, consider fundamental data architecture and make
+some decisions about how you’re modeling data. For example, consider building a
+simple grocery list app. A user should be able to create, read, update, and
+delete grocery lists.
+
+A single file collection stores items as an array nested inside each grocery
+list:
+
+```js
+// grocerylists.json
+{
+ "3255": {
+ "items": [
+ "1 Head of Lettuce",
+ "Haralson apples"
+ ]
+ },
+ // ...more lists with items
+}
+```
+
+This is conceptually the simplest way to manage grocery lists. When you read a
+`/grocerylists.json` file with `getFile()`, you get back one or more grocery
+lists and their items. When you write a single list, the `putFile()` method
+overwrites the entire list. So, a write operation for a new or updated grocery
+list must submit all existings lists as well.
+
+Further, because this runs on the client where anything can go wrong. If the
+client-side code encounters a parsing error with a user-input value and you
+could overwrite the entire file with:
+
+`line 6: Parsing Error: Unexpected token.`
+
+Further, a single file makes pagination impossible and if your app stores a
+single file for all list you have less control over file permissions. To avoid
+these issues, you can create an index file that stores an array of IDs. These
+IDs point to a name of another file in a `grocerylists` folder.
+
+![](images/multiple-lists.png)
+
+This design allows you to get only the files you need and avoid accidentally
+overwriting all lists. Further, you’re only updating the index file when you add
+or remove a grocery list; updating a list has no impact.
+
+
+## Add support for user status submission and lookup
+
+In this step, you add three `blockstack.js` methods that support posting of "statuses". These are the `putFile()`, `getFile()`, and `lookupProfile()` methods.
+
+1. Open the `src/components/Profile.jsx` file.
+
+2. Expand the `import from blockstack` statement with data methods.
+
+ The `Person` object holds a Blockstack profile. Add `putFile`, `getFile`,
+ and `lookupProfile` after `Person`.
+
+ When you are done, the import statement should look like the following:
+
+ ```javascript
+ import {
+ isSignInPending,
+ loadUserData,
+ Person,
+ getFile,
+ putFile,
+ lookupProfile
+ } from 'blockstack';
+ ```
+
+3. Replace the `constructor()` initial state so that it holds the key properties required by the app.
+
+ This code constructs a Blockstack `Person` object to hold the profile. Your constructor should look like this:
+
+ ```javascript
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ person: {
+ name() {
+ return 'Anonymous';
+ },
+ avatarUrl() {
+ return avatarFallbackImage;
+ },
+ },
+ username: "",
+ newStatus: "",
+ statuses: [],
+ statusIndex: 0,
+ isLoading: false
+ };
+ }
+ ```
+
+
+4. Locate the `render()` method.
+5. Modify the `render()` method to add a text input and submit button to the application.
+
+ The following code echos the `person.name` and `person.avatarURL`
+ properties from the profile on the display:
+
+ ```javascript
+ render() {
+ const { handleSignOut } = this.props;
+ const { person } = this.state;
+ const { username } = this.state;
+
+ return (
+ !isSignInPending() && person ?
+
: null
+ );
+ }
+ ```
+
+ This code allows the application to post statuses. It also displays the
+ user's Blockstack ID. To display this, your app must extract the ID from the
+ user profile data.
+
+6. Locate the `componentWillMount()` method.
+7. Add the `username` property below the `person` property.
+
+ You'll use the Blockstack `loadUserData()` method to access the `username`.
+
+
+ ```javascript
+ componentWillMount() {
+ this.setState({
+ person: new Person(loadUserData().profile),
+ username: loadUserData().username
+ });
+ }
+ ```
+
+7. Add two methods to handle the status input events:
+
+ ```javascript
+ handleNewStatusChange(event) {
+ this.setState({newStatus: event.target.value})
+ }
+
+ handleNewStatusSubmit(event) {
+ this.saveNewStatus(this.state.newStatus)
+ this.setState({
+ newStatus: ""
+ })
+ }
+ ```
+
+8. Add a `saveNewStatus()` method to save the new statuses.
+
+ ```javascript
+ saveNewStatus(statusText) {
+ let statuses = this.state.statuses
+
+ let status = {
+ id: this.state.statusIndex++,
+ text: statusText.trim(),
+ created_at: Date.now()
+ }
+
+ statuses.unshift(status)
+ const options = { encrypt: false }
+ putFile('statuses.json', JSON.stringify(statuses), options)
+ .then(() => {
+ this.setState({
+ statuses: statuses
+ })
+ })
+ }
+ ```
+
+9. Save the `Profile.jsk` file.
+
+ After the application compiles successfully, your application should appears as follows:
+
+ ![](images/display-complete.png)
+
+10. Enter your status in the text box and press the **Submit** button.
+
+ At this point, nothing is blogged. In the next section you add code to display
+ the statuses back to the user as a blog entry.
+
+## Fetch and display statuses
+
+Update `Profile.jsx` again.
+
+1. Go back to the `render()` method.
+2. Locate the `
` containing the text input and **Submit** button.
+3. Right after this opening `div` element, add this block.
+
+ ```javascript
+
+ ```
+ This loads existing state. Your code needs to fetch statuses on page load.
+
+4. Add a new method called `fetchData()` after the `statuses.unshift(status)` section.
+
+ ```javascript
+
+ fetchData() {
+ this.setState({ isLoading: true })
+ const options = { decrypt: false }
+ getFile('statuses.json', options)
+ .then((file) => {
+ var statuses = JSON.parse(file || '[]')
+ this.setState({
+ person: new Person(loadUserData().profile),
+ username: loadUserData().username,
+ statusIndex: statuses.length,
+ statuses: statuses,
+ })
+ })
+ .finally(() => {
+ this.setState({ isLoading: false })
+ })
+ }
+ ```
+
+5. Call `fetchData()` from the `componentDidMount()` method
+
+ ```javascript
+
+ componentDidMount() {
+ this.fetchData()
+ }
+ ```
+
+6. Save the file.
+
+ After the application compiles successfully, users are able to **Submit**
+ multiple statuses and review them in the app.
+
+ ![](images/saving-status.png)
+
+## Change the style
+
+1. Edit the `src/styles/style.css` file.
+2. Replace the content with the following:
+
+
+ ```css
+ /* Globals */
+ a,a:focus,a:hover{color:#fff;}
+ html,body{height:100%;text-align:center;background-color:#191b22;}
+ body{color:#fff}
+ .hide{display:none;}
+ .landing-heading{font-family:'Lato',Sans-Serif;font-weight:400;}
+
+ /* Buttons */
+ .btn{font-family:'Lato',Sans-Serif;padding:0.5625rem 2.5rem;font-size:0.8125rem;font-weight:400;line-height:1.75rem;border-radius:0!important;-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;-ms-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;}
+ .btn-lg{font-size:1.5rem;padding:0.6875rem 3.4375rem;line-height:2.5rem;}
+ .btn:focus,.btn:active:focus,.btn.active:focus{outline:none;}
+ .btn-primary{color:#fff;border:1px solid #2C96FF;background-color:#2C96FF;}
+ .btn-primary:hover,.btn-primary:focus,.btn-primary:active{color:#fff;border:1px solid #1a6ec0;background-color:#1a6ec0;}
+
+ /* Avatar */
+ .avatar{width:100px;height:100px;}
+ .avatar-section{margin-bottom:25px;display:flex;text-align:left;}
+ .username{margin-left:20px;}
+
+ /* Scaffolding */
+ .site-wrapper{display:table;width:100%;height:100vh;min-height:100%;}
+ .site-wrapper-inner{display:flex;flex-direction:column;justify-content:center;margin-right:auto;margin-left:auto;width:100%;height:100vh;}
+ .panel-authed{padding:0 0 0 0;}
+
+ /* Home button */
+ .btn-home-hello{position:absolute;font-family:'Source Code Pro',monospace;font-size:11px;font-weight:400;color:rgba(255,255,255,0.85);top:15px;left:15px;padding:3px 20px;background-color:rgba(255,255,255,0.15);border-radius:6px;-webkit-box-shadow:0px 0px 20px 0px rgba(0,0,0,0.15);-moz-box-shadow:0px 0px 20px 0px rgba(0,0,0,0.15);box-shadow:0px 0px 20px 0px rgba(0,0,0,0.15);}
+
+ /* Input */
+ input, textarea{color:#000;padding:10px;}
+ .input-status{width:100%;height:70px;border-radius:6px;}
+ .new-status{text-align:right;}
+
+ /* Statuses */
+ .statuses{padding-top:30px;}
+ .status{margin:15px 0px;padding:20px;background-color:#2e2e2e;border-radius:6px}
+ ```
+
+3. Save and close the `src/styles/style.css` file.
+
+ After the application compiles, you should see the following:
+
+ ![Multi-reader storage authentication](images/multi-player-storage-status.png)
+
+
+At this point, you have a basic micro-blogging app that users can use to post and
+view statuses. However, there's no way to view other users' statuses. You'll add
+that in the next section.
+
+## Lookup user profiles
+
+Let's now modify the `Profile.jsx` file to display profiles of other users. You'll
+be using the `lookupProfile()` method that you added to the `import` statement
+earlier. `lookupProfile()` takes a single parameter that is the Blockstack ID of
+the profile and returns a profile object.
+
+### Add a new route
+
+Make some changes to the routing structure of your app so that users can view
+other users' profiles by visiting `http://localhost:8080/other_user.id`
+
+
+1. Make sure you are in the root of your `publik` project.
+2. Install `react-router`:
+
+ ```bash
+ npm install --save react-router-dom
+ ```
+
+3. Edit `src/index.js` file.
+4. Add an `import` to the file at the top:
+
+ ```javascript
+ import { BrowserRouter } from 'react-router-dom'
+ ```
+
+5. Change the `ReactDOM.render()` method in `src/index.js` to:
+
+ ```javascript
+ ReactDOM.render((
+
+
+
+ ), document.getElementById('root'));
+ ```
+6. Save and close the `src/index.js` file.
+7. Edit the `src/components/App.jsx` file.
+8. Add the new route by importing the `Switch` and `Route` components from `react-router-dom`:
+
+ ```javascript
+ import { Switch, Route } from 'react-router-dom'
+ ```
+9. Locate this line below in the `render()` method:
+
+ ```javascript
+ :
+ ```
+
+10. Replace it with the following:
+
+ ```javascript
+ :
+
+
+ }
+ />
+
+ ```
+
+ This sets up a route and captures the route parameter the app will use as the profile lookup username.
+
+11. Save and close the the `src/components/App.jsx` file.
+
+
+### Add a rule to process URL paths with . (dot)
+
+You also need to add a rule to your webpack config so that you can properly
+process URL paths that contain the `.` (dot) character for example,
+`http://localhost:8080/other_user.id`
+
+**NOTE**: In a production app, you must ensure the web server is configured to handle this.
+
+
+1. Open `webpack.config.js` in the root project directory and locate the following line:
+
+ ```javascript
+ historyApiFallback: true,
+ ```
+
+2. Replace it with this:
+
+ ```javascript
+ historyApiFallback: {
+ disableDotRule: true
+ },
+ ```
+
+ You will need to run `npm start` again for this change to take effect. Don't
+ worry, there is a later step for that to remind you.
+
+3. Save and close the `webpack.config.js` file.
+
+4. Edit the `src/components/Profile.jsx` file.
+5. Add a single method that determines if the app is viewing the local user's profile or another user's profile.
+
+ ```javascript
+ isLocal() {
+ return this.props.match.params.username ? false : true
+ }
+ ```
+
+ You use `isLocal()` to check if the user is viewing the local user profile or another user's profile. If it's the local user profile, the app runs the `getFile()` function you added in an earlier step. Otherwise, the app looks up the profile belonging to the `username` using the `lookupProfile()` method.
+
+6. Modify the `fetchData()` method like so:
+
+ ```javascript
+ fetchData() {
+ this.setState({ isLoading: true })
+ if (this.isLocal()) {
+ const options = { decrypt: false }
+ getFile('statuses.json', options)
+ .then((file) => {
+ var statuses = JSON.parse(file || '[]')
+ this.setState({
+ person: new Person(loadUserData().profile),
+ username: loadUserData().username,
+ statusIndex: statuses.length,
+ statuses: statuses,
+ })
+ })
+ .finally(() => {
+ this.setState({ isLoading: false })
+ })
+ } else {
+ const username = this.props.match.params.username
+
+ lookupProfile(username)
+ .then((profile) => {
+ this.setState({
+ person: new Person(profile),
+ username: username
+ })
+ })
+ .catch((error) => {
+ console.log('could not resolve profile')
+ })
+ }
+ }
+ ```
+
+ **NOTE**: For `https` deployments, the default Blockstack Core API endpoint for name
+ lookups should be changed to point to a core API served over `https`.
+ Otherwise, name lookups fail due to browsers blocking mixed content.
+ Refer to the [Blockstack.js
+ documentation](http://blockstack.github.io/blockstack.js/#getfile) for
+ details.
+
+7. Add the following block to `fetchData()` right after the call to `lookupProfile(username)... catch((error)=>{..}` block:
+
+ ```javascript
+ const options = { username: username, decrypt: false }
+ getFile('statuses.json', options)
+ .then((file) => {
+ var statuses = JSON.parse(file || '[]')
+ this.setState({
+ statusIndex: statuses.length,
+ statuses: statuses
+ })
+ })
+ .catch((error) => {
+ console.log('could not fetch statuses')
+ })
+ .finally(() => {
+ this.setState({ isLoading: false })
+ })
+ ```
+
+ This fetches the user statuses.
+
+ Finally, you must conditionally render the logout button, status input textbox, and submit button so they don't show up when viewing another user's profile.
+
+8. Replace the `render()` method with the following:
+
+ ```javascript
+ render() {
+ const { handleSignOut } = this.props;
+ const { person } = this.state;
+ const { username } = this.state;
+
+ return (
+ !isSignInPending() && person ?
+
: null
+ );
+ }
+ ```
+
+ ### This checks to ensure that users are viewing their own profile, by wrapping the **Logout** button and inputs with the `{isLocal() && ...}` condition.
+
+### Put it all together
+
+1. Stop the running application by sending a CTL-C.
+2. Restart the application so that the disabling of the `.` (dot) rule takes effect.
+
+ ```bash
+ npm start
+ ```
+
+3. Point your browser to `http://localhost:8080/your_blockstack.id` to see the final application.
+
+
+
+## Wrapping up
+
+Congratulations, you are all done! We hope you've enjoyed learning a bit more
+about Blockstack. To use a working version of the app go
+[here](http://publik.ykliao.com).
diff --git a/_browser/purchase-id.md b/_browser/purchase-id.md
new file mode 100644
index 00000000..5e34c869
--- /dev/null
+++ b/_browser/purchase-id.md
@@ -0,0 +1,29 @@
+---
+layout: usenew
+permalink: /:collection/:path.html
+---
+# Purchase your own domain ID
+
+Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas faucibus
+cursus purus, fermentum consequat nisl consequat vel.In non posuere velit.
+Pellentesque rutrum molestie arcu ac rhoncus. Ut id pretium ligula. Mauris vel
+quam ac nisl fringilla tincidunt.
+
+
+Suspendisse cursus venenatis ligula a porta. Vestibulum
+ultricies elit eget leo dapibus, nec pulvinar risus porttitor. Integer vitae
+lectus at tellus consectetur sollicitudin. Ut cursus finibus feugiat. Sed purus
+ipsum, viverra congue velit vel, finibus vestibulum orci. Aliquam vitae vehicula
+nisl. Phasellus semper aliquet imperdiet. Vivamus feugiat leo quis metus
+facilisis congue. Nullam vel lectus sit amet enim aliquet sagittis vitae euismod
+risus.
+
+Suspendisse ipsum turpis, malesuada sit amet varius eget, auctor vitae lectus.
+Maecenas sit amet tellus metus. Sed in condimentum mi. Nulla ac tincidunt leo.
+Suspendisse lectus elit, facilisis non mollis eu, rhoncus vel augue. Ut tempus
+vel felis sit amet viverra. Aenean eu congue orci. Morbi massa mauris,
+
+ullamcorper ac odio nec, mattis auctor turpis. Sed rhoncus viverra elit. In hac
+habitasse platea dictumst. Vivamus eget mauris nec odio fringilla facilisis.
+Cras id ligula at eros cursus varius. Quisque semper nulla ut lobortis
+consequat. Aliquam hendrerit a neque id tempor. Sed porta id ligula in iaculis.
diff --git a/_browser/terms.md b/_browser/terms.md
new file mode 100644
index 00000000..3baf14a7
--- /dev/null
+++ b/_browser/terms.md
@@ -0,0 +1,14 @@
+---
+layout: usenew
+permalink: /:collection/:path.html
+---
+# Glossary
+
+
+{% for member in site.data.glossary %}
+
+
{{ member.Term }}
+
{{ member.Definition }}
+
+{% endfor %}
+
diff --git a/_browser/todo-list.md b/_browser/todo-list.md
new file mode 100644
index 00000000..7c328f4d
--- /dev/null
+++ b/_browser/todo-list.md
@@ -0,0 +1,338 @@
+---
+layout: learn
+permalink: /:collection/:path.html
+---
+# Todo List Application Tutorial
+
+In this tutorial, you build the code for and run a single-page application (SPA)
+with Blockstack and Vue.js. Once the application is running, you take a tour
+through the applications’ Blockstack functionality. You’ll learn how it manages
+authentiation using a Blockstack ID and how it stores information associated
+with that ID using Blockstack Storage (Gaia).
+
+* TOC
+{:toc}
+
+{% include note.html content="This tutorial was written on macOS High Sierra 10.13.4. If you use a Windows or Linux system, you can still follow along. However, you will need to \"translate\" appropriately for your operating system. Additionally, this tutorial assumes you are accessing the Blockstack Browser web application via Chrome. The application you build will also work with a local installation and/or with browsers other than Chrome. " %}
+
+If you prefer a video, you can view a video of the tutorial.
+
+## About this tutorial and the prerequisites you need
+For this tutorial, we will use the following tools:
+
+* `npm` to manage dependencies and scripts
+* `browserify` to compile node code into browser-ready code
+* `blockstack.js` to authenticate the user and work with the user’s identity/profile information
+
+At minimum, Blockstack requires macOS High Sierra. This tutorial was written for a user running macOS High Sierra 10.13.4. The application you build is a React.js application that is completely decentralized and server-less. While not strictly required to follow along, basic familiarity with React.js is helpful.
+
+When complete, the app is capable of the following:
+
+* authenticating users using Blockstack
+* posting new statuses
+* displaying statuses in the user profile
+* looking up the profiles and statuses of other users
+
+The basic identity and storage services are provided by blockstack.js. To test the application, you need to have already registered a Blockstack ID.
+
+The tutorial relies on the `npm` dependency manager. Before you begin, verify you have installed `npm` using the `which` command to verify.
+
+```bash
+$ which npm
+/usr/local/bin/npm
+```
+If you don’t find `npm` in your system, [install it](https://www.npmjs.com/get-npm).
+
+
+Finally, make sure you have [created at least one Blockstack ID]({{site.baseurl}}/browser/ids-introduction.html#create-an-initial-blockstack-id).
+You’ll use this ID to interact with the application.
+
+## Install the application code and retrieve the dependencies
+
+You can clone the source code with `git` or [download and unzip the code from
+the
+repository](https://github.com/blockstack/blockstack-todos/archive/master.zip).
+These instructions assume you are cloning.
+
+
+1. Install the code by cloning it.
+
+ ```
+ $ git clone git@github.com:blockstack/blockstack-todos.git
+ ```
+
+2. Change to directory to the root of the code.
+
+ ```
+ $ cd blockstack-todos
+ ```
+
+2. Use `yarn` to install the dependencies.
+
+
+ ```
+ $ yarn install
+ yarn install v1.9.2
+ info No lockfile found.
+ ...
+ [4/5] 🔗 Linking dependencies...
+ [5/5] 📃 Building fresh packages...
+ success Saved lockfile.
+ ✨ Done in 19.90s.
+ ```
+
+The Todo application has a basic Vue.js structure. There are several configuration files but the central programming files are in the `src` directory:
+
+| File | Description |
+|-----------------|-------------|
+| `main.js` | Application initialization. |
+| `App.vue ` | Code for handling the `authResponse`. |
+| `Landing.vue ` | Code for the initial sign on page. |
+| `Dashboard.vue` | Application data storage and user sign out. |
+
+
+## Sign into the application
+
+The example application runs in a node server on your local host. In the this section, you start the application and interact with it.
+
+1. Make sure you are in the root of the code base.
+
+ ```bash
+ $ pwd /Users/moxiegirl/repos/blockstack-todos
+ Start the application.
+ ```
+
+2. Start the application.
+
+ ```
+ $ npm run start
+ ```
+
+ You should see a simple application:
+
+ ![](images/todo-sign-in.png)
+
+ 2. Choose **Sign In with Blockstack**.
+
+ If you have already signed into Blockstack the application prompts you to select the ID to use. If you aren’t signed in, Blockstack prompts you to:
+
+ ![](images/login-choice.png)
+
+ If the login to the application is successful, the user is presented with the application:
+
+ ![](images/todo-app.png)
+
+## Understand the sign in process
+
+Clicking the Sign In With Blockstack button brings up a modal that prompts you
+to sign in with an existing ID or create a new ID. When Blockstack is provided
+an ID, it generates an ephemeral key within the application. An ephemeral key is
+generated for each execution of a key establishment process. This key is just
+used for the particular instance of the application, in this case to sign a Sign
+In request.
+
+A Blockstack Core node also generates a public key token which is sent to the
+browser as an `authRequest` from the browser to your core node. The signed
+authentication request is sent to Blockstack through a JSON Web Token (JWT).
+Blocktack passes the token in via a URL query string in the authRequest
+parameter:
+
+`https://browser.blockstack.org/auth?authRequest=j902120cn829n1jnvoa...`
+
+To decode the token and see what information it holds:
+
+1. Copy the `authRequest` string from the URL.
+2. Navigate to [jwt.io](https://jwt.io/).
+3. Paste the full token there.
+
+ The output should look similar to below:
+
+ ```json
+ {
+ "jti": "3i96e3ad-0626-4e32-a316-b243154212e2",
+ "iat": 1533136622,
+ "exp": 1533140228,
+ "iss": "did:btc-addr:1Nh8oQTunbEQWjrL666HBx2qMc81puLmMt",
+ "public_keys": [
+ "0362173da080c6e1dec0653fa9a3eff5f5660546e387ce6c24u04a90c2fe1fdu73"
+ ],
+ "domain_name": "http://localhost:8080",
+ "manifest_uri": "http://localhost:8080/manifest.json",
+ "redirect_uri": "http://localhost:8080/",
+ "version": "1.2.0",
+ "do_not_include_profile": true,
+ "supports_hub_url": true,
+ "scopes": [
+ "store_write"
+ ]
+ }
+ ```
+
+ >**Note**:
+ > * The `iss` property is a decentralized identifier or `did`. This identifies you and your name to the application. The specific `did` is a `btc-addr`.
+ > * The Blockstack JWT implementation is different from other implementations because of the underlying cryptography we employ. There are libraries in [Javascript](https://github.com/blockstack/jsontokens-js) and [Ruby](https://github.com/blockstack/ruby-jwt-blockstack) available on the Blockstack Github to allow you to work with these tokens.
+
+When the Blockstack node receives the `authRequest`, it generates a session token
+and returns an authentication response to the application. This response is
+similar to the `authRequest` above in that the `authResponse` includes a private key
+intended only for the application. This allows the application to encrypt data
+on your personal Blockstack storage.
+
+After the completion of this process, the user is logged in.
+
+## Undder the covers in the sign in code
+
+Now, go to the underlying `blockstack-todo` code you cloned or downloaded. Sign
+in and sign out is handled in each of these files:
+
+| File | Description |
+|-----------------|-------------|
+| `App.vue ` | Handles the `authResponse`. |
+| `Landing.vue ` | Generates the `authRequest`. |
+| `Dashboard.vue` | Handles sign out. |
+
+The `src/components/Landing.vue` code calls a [`redirectToSignIn()`](https://blockstack.github.io/blockstack.js#redirectToSignIn) function which generates the `authRequest` and redirects the user to the Blockstack authenticator:
+
+```js
+signIn () {
+ const blockstack = this.blockstack
+ blockstack.redirectToSignIn()
+}
+```
+
+Once the user authenticates, the application handles the `authResponse` in the `src/App.vue` file. :
+
+```js
+if (blockstack.isUserSignedIn()) {
+ this.user = blockstack.loadUserData().profile
+} else if (blockstack.isSignInPending()) {
+ blockstack.handlePendingSignIn()
+ .then((userData) => {
+ window.location = window.location.origin
+ })
+}
+```
+
+If [`blockstack.isUserSignedIn()`](https://blockstack.github.io/blockstack.js/#isusersignedin) is true, the user was previously signed in so Blockstack pulls the data from the browser and uses it in our application. If the check on [`blockstack.isSignInPending()`](https://blockstack.github.io/blockstack.js/#issigninpending) is true, a previous `authResponse` was sent to the application but hasn't been processed yet. The `handlePendingSignIn()` function processes any pending sign in.
+
+Signout is handled in `src/components/Dashboard.vue`.
+
+```js
+signOut () {
+ this.blockstack.signUserOut(window.location.href)
+}
+```
+
+The method allows the application creator to decide where to redirect the user upon Sign Out:
+
+
+## Working with the application
+
+Now, trying adding a few itmes to the todo list. For example, try making a list of applications you want to see built on top of Blockstack:
+
+![](images/make-a-list.png)
+
+Each list is immediately stored in the Gaia Hub linked to your Blockstack ID.
+For more information about the Gaia hub, see the [hub
+repository](https://github.com/blockstack/gaia). You can fetch the `todos.json`
+file you just added by opening the Javascript console and running the following
+command:
+
+```Javascript
+blockstack.getFile("todos.json", { decrypt: true }).then((file) => {console.log(file)})
+```
+
+You should see a JSON with the todos you just added:
+
+```json
+[
+ {
+ "id":2,
+ "text":"Software package manager secured by the blockchain",
+ "completed":false
+ },
+ {
+ "id":1,
+ "text":"Mutable torrents with human readable names",
+ "completed":false
+ },
+ {
+ "id":0,
+ "text":"Decentralized twitter",
+ "completed":false
+ }
+]
+```
+
+Add another todo and check it off. When you fetch the newly generated file
+using the Javascript console, the results reflect your change. Look for `"completed":true`:
+
+```json
+[
+ {
+ "id":3,
+ "text":"Blockstack Todo",
+ "completed":true
+ },
+ {
+ "id":2,
+ "text":"Software package manager secured by the blockchain",
+ "completed":false
+ },
+ ...
+]
+```
+
+Now that you have seen the application in action, dig into how it works.
+
+
+## Implementing storage
+
+Go to the underlying `blockstack-todo` code you cloned or downloaded. The
+application interactions with your Gaia Hub originate in the
+`src/components/Dashboard.vue` file. First, examine where the changes to the
+Todos are processed:
+
+```js
+todos: {
+ handler: function (todos) {
+ const blockstack = this.blockstack
+
+ // encryption is now enabled by default
+ return blockstack.putFile(STORAGE_FILE, JSON.stringify(todos))
+ },
+ deep: true
+}
+```
+
+The `todos` JSON object is passed in and the
+[`blockstack.putFile()`](https://blockstack.github.io/blockstack.js/#putfile)
+method to store it in a Gaia Hub.
+
+The code needs to read the Todo items from the storage with the [`blockstack.getFile()`](https://blockstack.github.io/blockstack.js/#getfile) method which returns a promise:
+
+```js
+fetchData () {
+ const blockstack = this.blockstack
+ blockstack.getFile(STORAGE_FILE) // decryption is enabled by default
+ .then((todosText) => {
+ var todos = JSON.parse(todosText || '[]')
+ todos.forEach(function (todo, index) {
+ todo.id = index
+ })
+ this.uidCount = todos.length
+ this.todos = todos
+ })
+},
+```
+
+The `todos` data is retrieved from the promise.
+
+
+## Summary
+
+You now have everything you need to construct complex applications complete with authentication and storage on the Decentralized Internet. Why not try coding [a sample application that accesses multiple profiles](blockstack_storage.html).
+
+If you would like to explore the Blockstack APIs, you can visit the [Blockstack Core API](https://core.blockstack.org/) documentation or the [Blockstack JS API](https://blockstack.github.io/blockstack.js).
+
+Go forth and build!
diff --git a/_config.yml b/_config.yml
index b2d042bd..3e6b011a 100644
--- a/_config.yml
+++ b/_config.yml
@@ -108,6 +108,7 @@ titles_from_headings:
include:
- _redirects
exclude:
+ - packag-lock.json
- Guardfile
- '*/glossary.md'
- '*/README.md'
diff --git a/_core/.svn/entries b/_core/.svn/entries
new file mode 100644
index 00000000..48082f72
--- /dev/null
+++ b/_core/.svn/entries
@@ -0,0 +1 @@
+12
diff --git a/_core/.svn/format b/_core/.svn/format
new file mode 100644
index 00000000..48082f72
--- /dev/null
+++ b/_core/.svn/format
@@ -0,0 +1 @@
+12
diff --git a/_core/.svn/pristine/00/0065c15c897da8543e6ae1e151e2241a6f8a3cc4.svn-base b/_core/.svn/pristine/00/0065c15c897da8543e6ae1e151e2241a6f8a3cc4.svn-base
new file mode 100644
index 00000000..aadc8584
--- /dev/null
+++ b/_core/.svn/pristine/00/0065c15c897da8543e6ae1e151e2241a6f8a3cc4.svn-base
@@ -0,0 +1,2 @@
+
+The documentation has been moved to [docs.blockstack.org](https://docs.blockstack.org/), please update your bookmarks.
diff --git a/_core/.svn/pristine/01/017c583bfd92cb9cb47b857ff4576bc9817b5808.svn-base b/_core/.svn/pristine/01/017c583bfd92cb9cb47b857ff4576bc9817b5808.svn-base
new file mode 100644
index 00000000..d789b274
--- /dev/null
+++ b/_core/.svn/pristine/01/017c583bfd92cb9cb47b857ff4576bc9817b5808.svn-base
@@ -0,0 +1,126 @@
+---
+layout: core
+permalink: /:collection/:path.html
+---
+# BNS Forks
+
+BNS effectively uses a public blockchain to store a database log. A BNS peer
+bootstraps itself by downloading and replaying the database log from the
+blockchain, and in doing so, will calculate the same name database state as
+every other (honest) BNS peer that has the same view of the blockchain.
+
+Crucially, BNS is built on top of a public blockchain that is *unaware* of BNS's existence.
+This means that the blockchain peers do not validate BNS transactions. Instead,
+the BNS peer needs to do so, and must know how to *reject* both invalid transactions
+as well as well-formed transactions from dishonest peers (i.e. peers that do not
+follow the same consensus rules).
+
+BNS nodes do not directly communicate with one another---by design, the set of
+BNS peers is not enumerable. The only shared communication medium between BNS
+peers is the blockchain.
+
+To identify and reject invalid and malicious transactions without the blockchain's help,
+the log of name operations embedded in the blockchain is constructed as a
+[fork\*-consistent](http://www.scs.stanford.edu/~jinyuan/bft2f.pdf) database
+log. Fork\*-consistency is a [consistency
+model](https://en.wikipedia.org/wiki/Consistency_model) whereby the state
+replicas in all of the nodes exhibit the following properties:
+
+* Each correct peer maintains a history of well-formed, valid state operations. In this
+ case, each correct BNS node maintains a copy of the history blockchain transactions
+that encoded well-formed, valid name operations.
+
+* Each honest peer's history contains the sequence of all operations that it
+ sent. That is, a user's BNS peer's transaction log will contain the sequence of all valid
+transactions that the user's client wrote to the blockchain.
+
+* If two peers accept operations *op* and *op'* from the same correct client,
+ then both of their logs will have the both operations in the same order. If
+*op'* was accepted before *op*, then both peers' logs are identical up to *op'*.
+In BNS, this means that if two peers both accept a given transaction, then it
+means that they have accepted the same sequence of prior transactions.
+
+This means that unlike with blockchains,
+there can be *multiple long-lived conflicting forks* of the BNS database log.
+However, due to fork\*-consistency, a correct BNS peer will only process *one*
+of these forks, and will *ignore* transactions from peers in other forks. In other words,
+fork\*-consistency partitions the set of BNS peers into different **fork-sets**,
+where all peers in a fork-set process each other's transactions, but the
+completely ignore peers in other fork-sets.
+
+BNS nodes identify which fork set they belong to using a **consensus hash**. The
+consensus hash is a cryptographic digest of a node's operation
+history. Each BNS peer calculates a new consensus hash each time it processes a
+new block, and stores the history of consensus hashes for each block it
+processed.
+
+Two honest BNS peers can quickly determine if they are in the same fork-set by querying
+each other's consensus hashes for a given block. If they match, then they are
+in the same fork-set (assming no hash collisions).
+
+A BNS client executes a name operation on a specific fork-set by including a
+recent consensus hash from that fork-set in the blockchain transaction.
+At the same time, the BNS consensus rules state that a transaction can only be
+accepted if it included a recent valid consensus hash.
+This means that all BNS nodes in the client's desired fork-set will accept
+the transaction, and all other BNS nodes not in the fork-set will ignore it.
+You can see where the consensus hash is included in blockchain transactions by reading
+the [transaction wire format]({{ site.baseurl }}/core/wire-format.html) document.
+
+## Fork-set Selection
+
+The blockchain linearizes the history of transactions, which means that
+in general, there exists a fork-set for each distinct set of BNS
+consensus rules. For example, the Blockstack Core [2016 hard fork](https://github.com/blockstack/blockstack-core/blob/master/release_notes/changelog-0.14.md)
+and [2017 hard fork](https://github.com/blockstack/blockstack-core/blob/master/release_notes/changelog-0.17.md) both introduced new consensus
+rules, which means at the time of this writing there are three possible fork-sets:
+the pre-2016 fork-set, the 2016-2017 fork-set, and the post-2017 fork-set.
+The [public BNS nodes](https://node.blockstack.org:6263) are always running
+in the fork-set with the latest consensus rules.
+
+BNS clients are incentivized to communicate with peers in the fork-set that has
+the most use, since this fork-set's name database will encode name/state
+bindings that are the most widely-accepted and understood by users.
+To identify this fork-set, a BNS client needs to learn one of
+its recent consensus hashes. Once it has a recent consensus hash, it can
+query an *untrusted* BNS node for a copy of
+its name database, and use the consensus hash to verify that the name database
+was used to generate it.
+
+How does a BNS node determine whether or not a consensus hash corresponds to the
+most widely-used fork-set? There are two strategies:
+
+* Determine whether or not a *characteristic transaction* was accepted by the
+widely-used fork-set. If a client knows that a specific transaction belongs to
+the widely-used fork-set and not others, then they can use the consensus hash to
+efficiently determine whether or not a given node belongs to this fork-set.
+
+* Determine how much "economic activity" exists in a fork-set by inspecting
+the blockchain for burned cryptocurrency tokens. Namespace and name
+registrations are structured in a way that sends cryptocurrency tokens to either
+a well-known burn address, or to an easily-queried pay-to-namespace-creator
+address.
+
+Both strategies rely on the fact that the consensus hash is calculated as a
+[Merkle skip-list](https://github.com/blockstack/blockstack-core/issues/146)
+over the BNS node's accepted transactions. A client can use a consensus hash to
+determine whether or not a transaction *T* was accepted by a node with *O(log
+n)* time and space complexity. We call the protocol for resolving a consensus hash to a specific transaction
+**Simplified Name Verification** (SNV). See our [paper on the subject](https://blockstack.org/virtualchain_dccl16.pdf)
+for details of how SNV works under the hood.
+
+If the client has a consensus hash and knows of a characteristic transaction in the widely-used fork-set,
+it can use SNV to determine whether or not a node belongs to the fork-set that accepted it.
+
+If the client knows about multiple conflicting consensus hashes,
+they can still use SNV to determine which one corresponds
+to the most-used fork-set. To do so, the client would use a
+[blockchain explorer](https://explorer.blockstack.org) to find the
+list of transactions that burned cryptocurrency tokens. Each of these
+transactions will be treated as potential characteristic transactions:
+the client would first select the subset of transactions that are well-formed
+BNS transactions, and then use SNV to determine which of them correspond to which
+consensus hashes. The client chooses the consensus hash that corresponds
+to the fork-set with the highest cumulative burn.
+
+Work is currently underway to automate this process.
diff --git a/_core/.svn/pristine/04/044964d98015e2c6153063f3928112cf781a8c26.svn-base b/_core/.svn/pristine/04/044964d98015e2c6153063f3928112cf781a8c26.svn-base
new file mode 100644
index 00000000..34ab7947
Binary files /dev/null and b/_core/.svn/pristine/04/044964d98015e2c6153063f3928112cf781a8c26.svn-base differ
diff --git a/_core/.svn/pristine/04/04a3f3d629b50687e19be6ad29be438b14b306a0.svn-base b/_core/.svn/pristine/04/04a3f3d629b50687e19be6ad29be438b14b306a0.svn-base
new file mode 100644
index 00000000..a7bce1f2
--- /dev/null
+++ b/_core/.svn/pristine/04/04a3f3d629b50687e19be6ad29be438b14b306a0.svn-base
@@ -0,0 +1,187 @@
+---
+layout: core
+permalink: /:collection/:path.html
+---
+# How to build a Profile Search Index
+
+The search subsystem for Blockstack Core creates an index for data associated
+with registered names in namespaces and makes that data searchable.
+
+The search subsystem is currently meant to index the .id namespace but can
+be easily expanded to include other namespaces.
+
+Currently there are two types of indexes to handle search queries:
+
+* Substring search on usernames, full names, twitter_handle (powered by MongoDB)
+* Raw Lucene index which handles searching extended data e.g., bio.
+
+Search will currently return upto a max of 20 results (can be less depending on the query)
+with data that follows structure of [blockstack IDs](https://github.com/blockstack/blockstack):
+
+In early 2017, the search subsystem was ported over to the new API system, where support for search is provided by the endpoint:
+
+```
+http://localhost:5000/search?query=
+```
+
+This document describes how to setup the search subsystem to respond at that endpoint.
+
+# Installation
+
+- **Step 1:** First, make sure you have [virtualenv installed](http://docs.python-guide.org/en/latest/dev/virtualenvs/).
+Then, setup the API and search subsystem:
+```
+$ sudo apt-get install -y mongodb memcached python-dev libmemcached-dev zlib1g-dev nginx
+$ sudo pip install uwsgi
+$ git clone https://github.com/blockstack/blockstack-core.git --branch api
+$ cd blockstack-core/
+$ sudo pip install .
+$ sudo pip install -r api/requirements.txt
+$ sudo mkdir /var/blockstack-search && sudo chown $USER:$USER /var/blockstack-search
+```
+
+- **Step 2:** Make sure you have Blockstack Core running locally (see [instructions](https://github.com/blockstack/blockstack-core/blob/master/README.md#quick-start)). We highly
+recommend using a local node because the search subsystem issues thousands of calls to
+Blockstack Core for re-indexing and remote nodes can slow down performance.
+
+- **Step 3:** Fetch the data for the .id namespace and respective profiles. Note, you may want to redirect stderr to a file, as there is a lot of debug output.
+
+```
+$ cd api/
+
+$ python -m search.fetch_data --fetch_namespace
+
+$ python -m search.fetch_data --fetch_profiles
+```
+
+- **Step 4:** Create the search index:
+
+```
+python -m search.basic_index --refresh
+```
+
+- **Step 5:** Enable search API endpoint:
+
+```
+$ sed -i 's/SEARCH_API_ENDPOINT_ENABLED \= False/SEARCH_API_ENDPOINT_ENABLED \= True/' config.py
+```
+
+# Usage
+
+You can quickly test the search index from the command line:
+
+```
+python -m search.substring_search --search_name "Fred Wil"
+python -m search.substring_search --search_twitter fredwil
+```
+
+You can also use the search API end-point:
+
+> curl -G {machine_ip}:port/search/name -d "query=muneeb"
+
+Sample Response:
+
+```
+{
+ "people": [
+ {
+ "profile": {
+ "website": [
+ {
+ "url": "http://muneebali.com",
+ "@type": "WebSite"
+ }
+ ],
+ "name": "Muneeb Ali",
+ "address": {
+ "addressLocality": "New York, NY",
+ "@type": "PostalAddress"
+ },
+ "image": [
+ {
+ "contentUrl": "https://s3.amazonaws.com/dx3/muneeb",
+ "@type": "ImageObject",
+ "name": "cover"
+ },
+ {
+ "contentUrl": "https://s3.amazonaws.com/kd4/muneeb",
+ "@type": "ImageObject",
+ "name": "avatar"
+ }
+ ],
+ "@type": "Person",
+ "description": "Co-founder of Blockstack. Interested in distributed systems and blockchains. Previously, PhD at Princeton."
+ },
+ "username": "muneeb"
+ },
+ {
+ "profile": {
+ "message": "This blockchain ID is reserved for Muneeb Ali. If this is you, please email support@onename.com to claim it for free.",
+ "status": "reserved"
+ },
+ "username": "muneebali"
+ },
+ {
+ "profile": {
+ "cover": {
+ "url": "https://s3.amazonaws.com/97p/HHE.jpg"
+ },
+ "v": "0.2"
+ },
+ "username": "muneebali1"
+ }
+
+ ]
+}
+```
+
+## Enabling Elastic Search
+
+### Requirements:
+
+```
+sudo apt-get install mongodb
+sudo apt-get install memcached libmemcached-dev
+sudo apt-get install python2.7-dev
+pip install -r requirements.txt
+```
+
+### Elastic Search
+
+Elastic Search library is not in github and resides at unix/lib/elastic
+
+the current version we're using is *0.90.2*. Download from:
+
+> wget https://download.elasticsearch.org/elasticsearch/elasticsearch/elasticsearch-0.90.2.zip
+
+before installing pylimbmc make sure [memcached]({{ site.baseurl }}/core/memcached.html) is installed.
+
+Ensure that mongodb and elastic search are running
+starting elastic search:
+
+```
+$elasticsearch (on mac)
+bin/elasticsearch -d (on linux)
+```
+
+To test if elastic search is running:
+
+> curl -X GET http://localhost:9200/
+
+returns:
+
+```
+{
+ "ok" : true,
+ "status" : 200,
+ "name" : "Angler",
+ "version" : {
+ "number" : "0.90.2",
+ "snapshot_build" : false,
+ "lucene_version" : "4.3.1"
+ },
+```
+
+Create Index:
+
+> python create_search_index.py --create_index
diff --git a/_core/.svn/pristine/06/0626aaf8b6b5b4c4e737538ebe9f864ca67bf1f3.svn-base b/_core/.svn/pristine/06/0626aaf8b6b5b4c4e737538ebe9f864ca67bf1f3.svn-base
new file mode 100644
index 00000000..29d87c72
Binary files /dev/null and b/_core/.svn/pristine/06/0626aaf8b6b5b4c4e737538ebe9f864ca67bf1f3.svn-base differ
diff --git a/_core/.svn/pristine/10/10387f589ddcab44bbe84d058e810fa70708ab25.svn-base b/_core/.svn/pristine/10/10387f589ddcab44bbe84d058e810fa70708ab25.svn-base
new file mode 100644
index 00000000..98b0d83a
--- /dev/null
+++ b/_core/.svn/pristine/10/10387f589ddcab44bbe84d058e810fa70708ab25.svn-base
@@ -0,0 +1,67 @@
+# About
+
+This document is for **Linux users who do not want to use Docker** to run the
+Blockstack Browser. Instructions are tailored for Ubuntu, but are similar on other distributions.
+
+# Setting up Blockstack Browser Node Application
+
+Install NodeJS through NodeSource PPA
+
+```
+curl -sL https://deb.nodesource.com/setup_7.x | sudo -E bash -
+sudo apt install -y nodejs
+```
+
+Download Blockstack Browser and install its dependencies
+
+```
+git clone https://github.com/blockstack/blockstack-browser.git
+cd blockstack-browser
+npm install node-sass
+npm install
+```
+
+Note that `blockstack-browser` depends on `node-sass` which can sometimes install strangely on Linux, running `npm install node-sass` before trying to install the other dependencies solves that problem.
+
+# Running Blockstack Browser
+
+Start the CORS proxy.
+
+```
+npm run dev-proxy &
+```
+
+Start the Node Application
+
+```
+npm run dev
+```
+
+Then you can open `http://localhost:3000/` in your browser to get to the Blockstack Browser.
+
+
+## Setting up a protocol handler
+
+If you'd like your browser to automatically handle links with the `blockstack:` protocol specifier, you will need to register a protocol handler with your desktop environment. In Ubuntu/Gnome, this can be done by creating a file
+
+`~/.local/share/applications/blockstack.desktop`
+
+With the following contents:
+
+```
+[Desktop Entry]
+Type=Application
+Terminal=false
+Exec=bash -c 'xdg-open http://localhost:3000/auth?authRequest=$(echo "%u" | sed s,blockstack:////*,,)'
+Name=Blockstack-Browser
+MimeType=x-scheme-handler/blockstack;
+```
+
+Then you need to make this file executable, and register it as a protocol handler.
+
+```
+$ chmod +x ~/.local/share/applications/blockstack.desktop
+$ xdg-mime default blockstack.desktop x-scheme-handler/blockstack
+```
+
+Now, `blockstack:` protocol URLs should get handled by your Blockstack Browser. If you're running Browser in your browser's private mode, you may have to copy and paste the link, as this protocol handler will try to open in a regular browser window.
diff --git a/_core/.svn/pristine/11/11ded89382de7db65698ea15b6d8adf1f69da3b7.svn-base b/_core/.svn/pristine/11/11ded89382de7db65698ea15b6d8adf1f69da3b7.svn-base
new file mode 100644
index 00000000..2140592f
--- /dev/null
+++ b/_core/.svn/pristine/11/11ded89382de7db65698ea15b6d8adf1f69da3b7.svn-base
@@ -0,0 +1,71 @@
+---
+layout: core
+permalink: /:collection/:path.html
+---
+# How to link your OpenBazaar GUID to your Blockstack ID
+{:.no_toc}
+* TOC
+{:toc}
+
+If you don't have the Blockstack CLI. Download and install it first. Instructions are [here](https://github.com/blockstack/blockstack-cli/blob/master/README.md). The rest of this tutorial assumes that you've already registered a name using the Blockstack CLI.
+
+## Step 1: Advanced Mode
+
+The first step is to activate "advanced mode" in the CLI. The command to do so is:
+
+```
+ $ blockstack set_advanced_mode on
+```
+
+## Step 2: Add an OpenBazaar Account
+
+The second step is to create an OpenBazaar account for your profile (the [Onename](https://onename.com) app also enabled to link your OpenBazaar GUID). The command to do so is:
+
+```
+ $ blockstack put_account "" "openbazaar" "" ""
+```
+
+The URL can be any valid URL; it won't be used by OpenBazaar. Here's an example, using the name `testregistration001.id` and the GUID `0123456789abcdef`:
+
+```
+ $ blockstack put_account "testregistration001.id" "openbazaar" "0123456789abcdef" "https://bazaarbay.org/@testregistration001"
+```
+
+The update should be instantaneous. You can verify that your store is present with `list_accounts`:
+
+```
+ $ blockstack list_accounts "testregistration001.id"
+ {
+ "accounts": [
+ {
+ "contentUrl": "https://bazaarbay.org/@testregistration001.id",
+ "identifier": "0123456789abcdef",
+ "service": "openbazaar"
+ }
+ ]
+ }
+````
+
+# Troubleshooting
+
+Common problems you might encounter.
+
+## Profile is in legacy format
+
+If you registered your blockstack ID before spring 2016, there's a chance that your profile is still in a legacy format. It will get migrated to the new format automatically if you update your profile on the [Onename](https://onename.com) app. However, you have to do this manually with the CLI.
+
+To do so, the command is:
+```
+ $ blockstack migrate
+```
+
+It will take a little over an hour to complete, but once finished, you'll be able to manage your accounts with the above commands (and do so with no delays).
+
+## Failed to broadcast update transaction
+
+This can happen during a `migrate` for one of a few reasons:
+* You do not have enough balance to pay the transaction fee (which is calculated dynamically).
+* Your payment address has unconfirmed transactions.
+* You can't connect to a Bitcoin node.
+
+To determine what's going on, you should try the command again by typing `BLOCKSTACK_DEBUG=1 blockstack ...` instead of `blockstack...`.
diff --git a/_core/.svn/pristine/20/202bb7feade42f6ac6aa89cffb73f9dcc5a5636d.svn-base b/_core/.svn/pristine/20/202bb7feade42f6ac6aa89cffb73f9dcc5a5636d.svn-base
new file mode 100644
index 00000000..b63e0536
--- /dev/null
+++ b/_core/.svn/pristine/20/202bb7feade42f6ac6aa89cffb73f9dcc5a5636d.svn-base
@@ -0,0 +1,461 @@
+# LEGACY DOCUMENTATION
+
+Please see the [latest Gaia documentation](https://github.com/blockstack/gaia)
+
+Gaia: The Blockstack Storage System
+====================================
+
+The Blockstack storage system, called "Gaia", is used to host each user's data
+without requiring users to run their own servers.
+
+Gaia works by hosting data in one or more existing storage systems of the user's choice.
+These storage systems include cloud storage systems like Dropbox and Google
+Drive, they include personal servers like an SFTP server or a WebDAV server, and
+they include decentralized storage systems like BitTorrent or IPFS. The point
+is, the user gets to choose where their data lives, and Gaia enables
+applications to access it via a uniform API.
+
+A high-level analogy is to compare Gaia to the VFS and block layer in a UNIX
+operating system kernel, and to compare existing storage systems to block
+devices. Gaia has "drivers" for each storage system that allow it to load,
+store, and delete chunks of data via a uniform interface, and it gives
+applications a familiar API for organizing their data.
+
+Applications interface with Gaia via the [Blockstack Core
+API](https://github.com/blockstack/blockstack-core/tree/master/api). Javascript
+applications connect to Gaia using [Blockstack Portal](https://github.com/blockstack/blockstack-portal),
+which helps them bootstrap a secure connection to Blockstack Core.
+
+# Datastores
+
+Gaia organizes data into datastores. A **datastore** is a filesystem-like
+collection of data that is backed by one or more existing storage systems.
+
+When a user logs into an application, the application will create or connect to
+the datastore that holds the user's data. Once connected, it can proceed to
+interact with its data via POSIX-like functions: `mkdir`, `listdir`, `rmdir`,
+`getFile`, `putFile`, `deleteFile`, and `stat`.
+
+A datastore has exactly one writer: the user that creates it. However, all data
+within a datastore is world-readable by default, so other users can see the
+owner's writes even when the owner is offline. Users manage access controls
+by encrypting files and directories to make them readable to other specific users.
+All data in a datastore is signed by a datastore-specific key on write, in order
+to guarantee that readers only consume authentic data.
+
+The application client handles all of the encryption and signing. The other
+participants---Blockstack Portal, Blockstack Core, and the storage
+systems---only ferry data back and forth between application clients.
+
+## Data Organization
+
+True to its filesystem inspiration, data in a datastore is organized into a
+collection of inodes. Each inode has two parts:
+
+* a **header**, which contains:
+
+ * the inode type (i.e. file or directory)
+
+ * the inode ID (i.e. a UUID4)
+
+ * the hash of the data it stores
+
+ * the size of the data it stores
+
+ * a signature from the user
+
+ * the version number
+
+ * the ID of the device from which it was sent (see Advanced Topics below)
+
+* a **payload**, which contains the raw bytes to be stored.
+
+ * For files, this is just the raw bytes.
+
+ * For directories, this is a serialized data structure that lists the names
+ and inode IDs of its children, as well as a copy of the header.
+
+The header has a fixed length, and is somewhat small--only a few hundred bytes.
+The payload can be arbitrarily large.
+
+## Data Consistency
+
+The reason for organizing data this way is to make cross-storage system reads
+efficient, even when there are stale copies of the data available. In this
+organization, reading an inode's data is a matter of:
+
+1. Fetching all copies of the header
+
+2. Selecting the header with the highest version number
+
+3. Fetching the payload from the storage system that served the latest header.
+
+This way, we can guarantee that:
+
+* The inode payload is fetched *once* in the common case, even if there are multiple stale copies of the inode available.
+
+* All clients observe the *strongest* consistency model offerred by the
+ underlying storage providers.
+
+* All readers observe a *minimum* consistency of monotonically-increasing reads.
+
+* Writers observe sequential consistency.
+
+This allows Gaia to interface with decentralized storage systems that make
+no guarantees regarding data consistency.
+
+*(Aside 1: The Core node keeps track of the highest last-seen inode version number,
+so if all inodes are stale, then no data will be returned).*
+
+*(Aside 2: In step 3, an error path exists whereby all storage systems will be
+queried for the payload if the storage system that served the fresh inode does
+not have a fresh payload).*
+
+# Accessing the Datastore
+
+Blockstack applications get access to the datastore as part of the sign-in
+process. Suppose the user wishes to sign into the application `foo.app`. Then,
+the following protocol is executed:
+
+![Gaia authentication](/docs/figures/gaia-authentication.png)
+
+1. Using `blockstack.js`, the application authenticates to Blockstack Portal via
+`makeAuthRequest()` and `redirectUserToSignIn()`.
+
+2. When Portal receives the request, it contacts the user's Core node to get the
+ list of names owned by the user.
+
+3. Portal redirects the user to a login screen, and presents the user with the
+ list of names to use. The user selects which name to sign in as.
+
+4. Now that Portal knows which name to use, and which application is signing in,
+ it loads the datastore private key and requests a Blockstack Core session
+token. This token will be used by the application to access Gaia.
+
+5. Portal creates an authentication response with `makeAuthResponse()`, which it
+ relays back to the application.
+
+6. The application retrieves the datastore private key and the Core session
+ token from the authentication response object.
+
+
+## Creating a Datastore
+
+Once the application has a Core session token and the datastore private key, it
+can proceed to connect to it, or create it if it doesn't exist. To do so, the
+application calls `datastoreConnectOrCreate()`.
+
+This method contacts the Core node directly. It first requests the public
+datastore record, if it exists. The public datastore record
+contains information like who owns the datastore, when it was created, and which
+drivers should be used to load and store its data.
+
+![Gaia connect](/docs/figures/gaia-connect.png)
+
+Suppose the user signing into `foo.app` does not yet have a datastore, and wants
+to store her data on storage providers `A`, `B`, and `C`. Then, the following
+protocol executes:
+
+1. The `datastoreConnectOrCreate()` method will generate a signed datastore record
+stating that `alice.id`'s public key owns the datastore, and that the drivers
+for `A`, `B`, and `C` should be loaded to access its data.
+
+2. The `datastoreConnectOrCreate()` method will call `mkdir()` to create a
+signed root directory.
+
+3. The `datastoreConnectOrCreate()` method will send these signed records to the Core node.
+The Core node replicates the root directory header (blue path), the root
+direcory payload (green path), and the datastore record (gold path).
+
+4. The Core node then replicates them with drivers `A`, `B`, and `C`.
+
+Now, storage systems `A`, `B`, and `C` each hold a copy of the datastore record
+and its root directory.
+
+*(Aside: The datastore record's consistency is preserved the same way as the
+inode consistency).*
+
+## Reading Data
+
+Once the application has a Core session token, a datastore private key, and a
+datastore connection object, it can proceed to read it. The available methods
+are:
+
+* `listDir()`: Get the contents of a directory
+
+* `getFile()`: Get the contents of a file
+
+* `stat()`: Get a file or directory's header
+
+Reading data is done by path, just as it is in UNIX. At a high-level, reading
+data involes (1) resolving the path to the inode, and (2) reading the inode's
+contents.
+
+Path resolution works as it does in UNIX: the root directory is fetched, then
+the first directory in the path, then the second directory, then the third
+directory, etc., until either the file or directory at the end of the path is
+fetched, or the name does not exist.
+
+### Authenticating Data
+
+Data authentication happens in the Core node,.
+This is meant to enable linking files and directories to legacy Web
+applications. For example, a user might upload a photo to a datastore, and
+create a public URL to it to share with friends who do not yet use Blockstack.
+
+By default, the Core node serves back the inode payload data
+(`application/octet-stream` for files, and `application/json` for directories).
+The application client may additionally request the signatures from the Core
+node if it wants to authenticate the data itself.
+
+### Path Resolution
+
+Applications do not need to do path resolution themselves; they simply ask the
+Blockstack Core node to do so on their behalf. Fetching the root directory
+works as follows:
+
+1. Get the root inode ID from the datastore record.
+
+2. Fetch all root inode headers.
+
+3. Select the latest inode header, and then fetch its payload.
+
+4. Authenticate the data.
+
+For example, if a client wanted to read the root directory, it would call
+`listDir()` with `"/"` as the path.
+
+![Gaia listdir](/docs/figures/gaia-listdir.png)
+
+The blue paths are the Core node fetching the root inode's headers. The green
+paths are the Core node selecting the latest header and fetching the root
+payload. The Core node would reply the list of inode names within the root
+directory.
+
+Once the root directory is resolved, the client simply walks down the path to
+the requested file or directory. This involves iteratively fetching a
+directory, searching its children for the next directory in the path, and if it
+is found, proceeding to fetch it.
+
+### Fetching Data
+
+Once the Core node has resolved the path to the base name, it looks up the inode
+ID from the parent directory and fetches it from the backend storage providers
+via the relevant drivers.
+
+For example, fetching the file `/bar` works as follows:
+
+![Gaia getFile](/docs/figures/gaia-getfile.png)
+
+1. Resolve the root directory (blue paths)
+
+2. Find `bar` in the root directory
+
+3. Get `bar`'s headers (green paths)
+
+4. Find the latest header for `bar`, and fetch its payload (gold paths)
+
+5. Return the contents of `bar`.
+
+## Writing Data
+
+There are three steps to writing data:
+
+* Resolving the path to the inode's parent directory
+
+* Creating and replicating the new inode
+
+* Linking the new inode to the parent directory, and uploading the new parent
+ directory.
+
+All of these are done with both `putFile()` and `mkdir()`.
+
+### Creating a New Inode
+
+When it calls either `putFile()` or `mkdir()`, the application client will
+generate a new inode header and payload and sign them with the datastore private
+key. Once it has done so successfully, it will insert the new inode's name and
+ID into the parent directory, give the parent directory a new version number,
+and sign and replicate it and its header.
+
+For example, suppose the client attempts to write the data `"hello world"` to `/bar`.
+To do so:
+
+![Gaia putFile](/docs/figures/gaia-putfile.png)
+
+1. The client executes `listDir()` on the parent directory, `/` (blue paths).
+
+2. If an inode by the name of `bar` exists in `/`, then the method fails.
+
+3. The client makes a new inode header and payload for `bar` and signs them with
+ the datastore private key. It replicates them to the datastore's storage
+drivers (green paths).
+
+4. The client adds a record for `bar` in `/`'s data obtained from (1),
+ increments the version for `/`, and signs and replicates `/`'s header and
+payload (gold paths).
+
+
+### Updating a File or Directory
+
+A client can call `putFile()` multiple times to set the file's contents. In
+this case, the client creates, signs, and replicates a new inode header and new
+inode payload for the file. It does not touch the parent directory at all.
+In this case, `putFile()` will only succeed if the parent directory lists an
+inode with the given name.
+
+A client cannot directly update the contents of a directory.
+
+## Deleting Data
+
+Deleting data can be done with either `rmdir()` (to remove an empty directory)
+or `deleteFile()` (to remove a file). In either case, the protocol executed is
+
+1. The client executes `listDir()` on the parent directory
+
+2. If an inode by the given name does not exist, then the method fails.
+
+3. The client removes the inode's name and ID from the directory listing, signs
+ the new directory, and replicates it to the Blockstack Core node.
+
+4. The client tells the Blockstack Core node to delete the inode's header and
+ payload from all storage systems.
+
+
+# Advanced Topics
+
+These features are still being implemented.
+
+## Data Integrity
+
+What happens if the client crashes while replicating new inode state? What
+happens if the client crashes while deleting inode state? The data hosted in
+the underlying data stores can become inconsistent with the directory structure.
+
+Given the choice between leaking data and rendering data unresolvable, Gaia
+chooses to leak data.
+
+### Partial Inode-creation Failures
+
+When creating a file or directory, Gaia stores four records in this order:
+
+* the new inode payload
+
+* the new inode header
+
+* the updated parent directory payload
+
+* the updated parent directory header
+
+If the new payload replicates successfully but the new header does not, then the
+new payload is leaked.
+
+If the new payload and new header replicate successfully, but neither parent
+directory record succeeds, then the new inode header and payload are leaked.
+
+If the new payload, new header, and updated parent directory payload replicate
+successfully, but the updated parent header fails, then not only are the new
+inode header and payload leaked, but also *reading the parent directory will
+fail due to a hash mismatch between its header and inode*. This can be detected
+and resolved by observing that the copy of the header in the parent directory
+payload has a later version than the parent directory header indicates.
+
+### Partial Inode-deletion Failures
+
+When deleting a file or directory, Gaia alters records in this order:
+
+* update parent directory payload
+
+* update parent directory header
+
+* delete inode header
+
+* delete inode payload
+
+Similar to partial failures from updating parent directories when creating
+files, if the client replicates the new parent directory inode payload but fails
+before it can update the header, then clients will detect on the next read that
+the updated payload is valid because it has a signed inode header with a newer
+version.
+
+If the client successfully updates the parent directory but fails to delete
+either the inode header or payload, then they are leaked. However, since the
+directory was updated, no correct client will access the deleted inode data.
+
+### Leak Recovery
+
+Gaia's storage drivers are designed to keep the inode data they store in a
+"self-contained" way (i.e. within a single folder or bucket). In the future,
+we will implement a `fsck`-like tool that will scan through a datastore and find
+the set of inode headers and payloads that are no longer referenced and delete
+them.
+
+## Multi-Device Support
+
+Contemporary users read and write data across multiple devices. In this
+document, we have thus far described datastores with the assumption that there
+is a single writer at all times.
+
+This assumption is still true in a multi-device setting, since a user is
+unlikely to be writing data with the same application simultaneously from two
+different devices.
+
+However, an open question is how multiple devices can access the same
+application data for a user. Our design goal is to **give each device its own
+keyring**, so if it gets lost, the user can revoke its access without having to
+re-key her other devices.
+
+To do so, we'll expand the definition of a datastore to be a **per-user,
+per-application, and per-device** collection of data. The view of a user's
+application data will be constructed by merging each device-specific
+datastore, and resolving conflicts by showing the "last-written" inode (where
+"last-written" is determined by a loosely-synchronized clock).
+
+For example, if a user uploads a profile picture from their phone, and then
+uploads a profile picture from their tablet, a subsequent read will query the
+phone-originated picture and the tablet-originated picture, and return the
+tablet-originated picture.
+
+The aforementioned protocols will need to be extended to search for inode
+headers not only on each storage provider, but also search for inodes on the
+same storage provider that may have been written by each of the user's devices.
+Without careful optimization, this can lead to a lot of inode header queries,
+which we address in the next topic.
+
+## A `.storage` Namespace
+
+Blockstack Core nodes can already serve as storage "gateways". That is, one
+node can ask another node to store its data and serve it back to any reader.
+
+For example, Alice can make her Blockstack Core node public and program it to
+store data to her Amazon S3 bucket and her Dropbox account. Bob can then post data to Alice's
+node, causing her node to replicate data to both providers. Later, Charlie can
+read Bob's data from Alice's node, causing Alice's node to fetch and serve back
+the data from her cloud storage. Neither Bob nor Charlie have to set up accounts on
+Amazon S3 and Dropbox this way.
+
+Since Alice is on the read/write path between Bob and Charlie and cloud storage,
+she has the opportunity to make optimizations. First, she can program her
+Core node to synchronously write data to
+local disk and asynchronously back it up to S3 and Dropbox. This would speed up
+Bob's writes, but at the cost of durability (i.e. Alice's node could crash
+before replicating to the cloud).
+
+In addition, Alice can program her Core node to service all reads from disk. This
+would speed up Charlie's reads, since he'll get the latest data without having
+to hit back-end cloud storage providers.
+
+Since Alice is providing a service to Bob and Charlie, she will want
+compensation. This can be achieved by having both of them send her money via
+the underlying blockchain.
+
+To do so, she would register her node's IP address in a
+`.storage` namespace in Blockstack, and post her rates per GB in her node's
+profile and her payment address. Once Bob and Charlie sent her payment, her
+node would begin accepting reads and writes from them up to the capacity
+purchased. They would continue sending payments as long as Alice provides them
+with service.
+
+Other experienced node operators would register their nodes in `.storage`, and
+compete for users by offerring better durability, availability, performance,
+extra storage features, and so on.
diff --git a/_core/.svn/pristine/24/2478a64988e118492fedc3f075faba53b2356e9c.svn-base b/_core/.svn/pristine/24/2478a64988e118492fedc3f075faba53b2356e9c.svn-base
new file mode 100644
index 00000000..ad4d7493
--- /dev/null
+++ b/_core/.svn/pristine/24/2478a64988e118492fedc3f075faba53b2356e9c.svn-base
@@ -0,0 +1,101 @@
+---
+layout: core
+permalink: /:collection/:path.html
+---
+# Manage BNS Names
+{:.no_toc}
+
+This section teaches you how to manage your namespace, it contains the
+following sections:
+
+* TOC
+{:toc}
+
+## Overview of management
+
+Once you register a BNS name, you have the power to change its zone file hash,
+change its public key hash, destroy it (i.e. render it unresolvable),
+or renew it. The BNS consensus rules ensure that *only* you, as the owner of
+the name's private key, have the ability to carry out these operations.
+
+Each of these operations are executed by sending a specially-formatted
+blockchain transaction to the blockchain, which BNS nodes read and process.
+The operations are listed below:
+
+| Transaction Type | Description |
+|------------------|-------------|
+| `NAME_UPDATE` | This changes the name's zone file hash. Any 20-byte string is allowed. |
+| `NAME_TRANSFER` | This changes the name's public key hash. In addition, the current owner has the option to atomically clear the name's zone file hash (so the new owner won't "receive" the zone file). |
+| `NAME_REVOKE` | This renders a name unresolvable. You should do this if your private key is compromised. |
+| `NAME_RENEWAL` | This pushes back the name's expiration date (if it has one), and optionally both sets a new zone file hash and a new public key hash. |
+
+The reference BNS clients---
+[blockstack.js](https://github.com/blockstack/blockstack.js) and the [Blockstack
+Browser](https://github.com/blockstack/blockstack-browser)---can handle creating
+and sending all of these transactions for you.
+
+## NAME_UPDATE ([live example](https://www.blocktrail.com/BTC/tx/e2029990fa75e9fc642f149dad196ac6b64b9c4a6db254f23a580b7508fc34d7))
+
+A `NAME_UPDATE` transaction changes the name's zone file hash. You would send
+one of these transactions if you wanted to change the name's zone file contents.
+For example, you would do this if you want to deploy your own [Gaia
+hub](https://github.com/blockstack/gaia) and want other people to read from it.
+
+A `NAME_UPDATE` transaction is generated from the name, a recent [consensus
+hash](#bns-forks), and the new zone file hash. The reference clients gather
+this information automatically. See the [transaction format]({{ site.baseurl }}/core/wire-format.html)
+document for details on how to construct this transaction.
+
+## NAME_TRANSFER ([live example](https://www.blocktrail.com/BTC/tx/7a0a3bb7d39b89c3638abc369c85b5c028d0a55d7804ba1953ff19b0125f3c24))
+
+A `NAME_TRANSFER` transaction changes the name's public key hash. You would
+send one of these transactions if you wanted to:
+
+* Change your private key
+* Send the name to someone else
+
+When transferring a name, you have the option to also clear the name's zone
+file hash (i.e. set it to `null`).
+This is useful for when you send the name to someone else, so the
+recipient's name does not resolve to your zone file.
+
+The `NAME_TRANSFER` transaction is generated from the name, a recent [consensus
+hash](#bns-forks), and the new public key hash. The reference clients gather
+this information automatically. See the [transaction format]({{ site.baseurl }}/core/wire-format.html)
+document for details on how to construct this transaction.
+
+## NAME_REVOKE ([live example](https://www.blocktrail.com/BTC/tx/eb2e84a45cf411e528185a98cd5fb45ed349843a83d39fd4dff2de47adad8c8f))
+
+A `NAME_REVOKE` transaction makes a name unresolvable. The BNS consensus rules
+stipulate that once a name is revoked, no one can change its public key hash or
+its zone file hash. The name's zone file hash is set to `null` to prevent it
+from resolving.
+
+You should only do this if your private key is compromised, or if you want to
+render your name unusable for whatever reason. It is rarely used in practice.
+
+The `NAME_REVOKE` operation is generated using only the name. See the
+[transaction format]({{ site.baseurl }}/core/wire-format.html) document for details on how to construct
+it.
+
+## NAME_RENEWAL ([live example](https://www.blocktrail.com/BTC/tx/e543211b18e5d29fd3de7c0242cb017115f6a22ad5c6d51cf39e2b87447b7e65))
+
+Depending in the namespace rules, a name can expire. For example, names in the
+`.id` namespace expire after 2 years. You need to send a `NAME_RENEWAL` every
+so often to keep your name.
+
+A `NAME_RENEWAL` costs both transaction fees and registration fees. You will
+pay the registration cost of your name to the namespace's designated burn address when you
+renew it. You can find this fee using the `/v1/prices/names/{name}` endpoint.
+
+When a name expires, it enters a month-long "grace period" (5000 blocks). It
+will stop resolving in the grace period, and all of the above operations will
+cease to be honored by the BNS consensus rules. You may, however, send a
+`NAME_RENEWAL` during this grace period to preserve your name.
+
+If your name is in a namespace where names do not expire, then you never need to
+use this transaction.
+
+When you send a `NAME_RENEWAL`, you have the option of also setting a new public
+key hash and a new zone file hash. See the [transaction format]({{ site.baseurl }}/core/wire-format.html)
+document for details on how to construct this transaction.
diff --git a/_core/.svn/pristine/2b/2bcef3ad406ebbebe4e24558cceb2ca2dcc93a18.svn-base b/_core/.svn/pristine/2b/2bcef3ad406ebbebe4e24558cceb2ca2dcc93a18.svn-base
new file mode 100644
index 00000000..f5fc6226
--- /dev/null
+++ b/_core/.svn/pristine/2b/2bcef3ad406ebbebe4e24558cceb2ca2dcc93a18.svn-base
@@ -0,0 +1,57 @@
+---
+layout: core
+permalink: /:collection/:path.html
+---
+# Creating a Namespace
+
+There are four steps to creating a namespace:
+
+1. **Send a `NAMESPACE_PREORDER` transaction** ([live example](https://www.blocktrail.com/BTC/tx/5f00b8e609821edd6f3369ee4ee86e03ea34b890e242236cdb66ef6c9c6a1b28)).
+This is the first step. This registers the *salted hash* of the namespace with BNS nodes, and burns the
+requisite amount of cryptocurrency. In addition, it proves to the
+BNS nodes that user has honored the BNS consensus rules by including
+a recent *consensus hash* in the transaction
+(see the section on [BNS forks](#bns-forks) for details).
+
+2. **Send a `NAMESPACE_REVEAL` transaction** ([live example](https://www.blocktrail.com/BTC/tx/ab54b1c1dd5332dc86b24ca2f88b8ca0068485edf0c322416d104c5b84133a32)).
+This is the second step. This reveals the salt and the namespace ID (pairing it with its
+`NAMESPACE_PREORDER`), it reveals how long names last in this namespace before
+they expire or must be renewed, and it sets a *price function* for the namespace
+that determines how cheap or expensive names its will be. The price function takes
+a name in this namespace as input, and outputs the amount of cryptocurrency the
+name will cost (i.e. by examining how long the name is, and whether or not it
+has any vowels or non-alphabet characters). The namespace creator
+has the option to collect name registration fees for the first year of the
+namespace's existence by setting a *namespace creator address*.
+
+3. **Seed the namespace with `NAME_IMPORT` transactions** ([live example](https://www.blocktrail.com/BTC/tx/c698ac4b4a61c90b2c93dababde867dea359f971e2efcf415c37c9a4d9c4f312)).
+Once the namespace has been revealed, the user has the option to populate it with a set of
+names. Each imported name is given both an owner and some off-chain state.
+This step is optional---namespace creators are not required to import names.
+
+4. **Send a `NAMESPACE_READY` transaction** ([live example](https://www.blocktrail.com/BTC/tx/2bf9a97e3081886f96c4def36d99a677059fafdbd6bdb6d626c0608a1e286032)).
+This is the final step of the process. It *launches* the namespace, which makes it available to the
+public. Once a namespace is ready, anyone can register a name in it if they
+pay the appropriate amount of cryptocurrency (according to the price funtion
+revealed in step 2).
+
+The reason for the `NAMESPACE_PREORDER/NAMESPACE_REVEAL` pairing is to prevent
+frontrunning. The BNS consensus rules require a `NAMESPACE_REVEAL` to be
+paired with a previous `NAMESPACE_PREORDER` sent within the past 24 hours.
+If it did not do this, then a malicious actor could watch the blockchain network
+and race a victim to claim a namespace.
+
+Namespaces are created on a first-come first-serve basis. If two people try to
+create the same namespace, the one that successfully confirms both the
+`NAMESPACE_PREORDER` and `NAMESPACE_REVEAL` wins. The fee burned in the
+`NAMESPACE_PREORDER` is spent either way.
+
+Once the user issues the `NAMESPACE_PREORDER` and `NAMESPACE_REVEAL`, they have
+1 year before they must send the `NAMESPACE_READY` transaction. If they do not
+do this, then the namespace they created disappears (along with all the names
+they imported).
+
+Developers wanting to create their own namespaces should read the [namespace
+creation]({{ site.baseurl }}/core/naming/namepsaces.html) document. It is highly recommended that
+developers individula support to create your own namespace, given the large amount of
+cryptocurrency at stake.
diff --git a/_core/.svn/pristine/2d/2d6e52c27f1eff453e769ac336a2fd2c844d3ae2.svn-base b/_core/.svn/pristine/2d/2d6e52c27f1eff453e769ac336a2fd2c844d3ae2.svn-base
new file mode 100644
index 00000000..b1f8e197
--- /dev/null
+++ b/_core/.svn/pristine/2d/2d6e52c27f1eff453e769ac336a2fd2c844d3ae2.svn-base
@@ -0,0 +1,87 @@
+---
+layout: core
+permalink: /:collection/:path.html
+---
+# Understand the Architecture
+
+The BNS node is the heart of the system. It is responsible for building up
+and replicating global name state.
+
+There are three parts to BNS that developers should be aware of. They are:
+
+* **The BNS indexer**. This module crawls the blockchain and builds
+ up its name database. BNS indexers do not contain any private or sensitive
+state, and can be deployed publicly. We maintain a fleet of them at
+`https://node.blockstack.org:6263` for developers to use to get started.
+
+* **The BNS API**. This module gives
+ developers a *stable RESTful API* for interacting with the BNS network.
+We provide one for developers to experiment with at `https://core.blockstack.org`.
+
+* **BNS clients**. These communicate with the BNS API module in order to
+ resolve names. Internally, they generate and send transactions to register
+and modify names.
+
+The BNS indexer and BNS API comprise the **BNS node**. An architectural schematic appears below.
+
+```
+ +-------------------------------------------------------+
+ RESTful | +----------------+ +--------------------+ |
++--------+ API | | | private API | | |
+| client |<------------>| BNS API module |<----------->| BNS indexer module | |
++--------+ | | | | | |
+ | | +----------------+ | +----------------+ | |
+ | | | | name database | | |
+ | | | +----------------+ | |
+ | | +--------------------+ |
+ | | BNS node ^ |
+ | +------------------------------------------|------------+
+ | |
+ | v
+ | blockchain transactions +--------------------+
+ +------------------------------------------------->| blockchain peer |
+ +--------------------+
+
+Figure 1: BNS architecture overview. Clients talk to the BNS API module to
+resolve names, and generate and send blockchain transactions to register and
+modify names. The API module talks to the indexer module and gives clients
+a stable, Web-accessible interface for resolving names. The indexer module reads
+the blochchain via a blockchain peer, over the blockchain's peer network.
+
+Blockstack Core currently implements the API module and indexer module as separate
+daemons (`blockstack api` and `blockstack-core`, respectively). However, this
+is an implementation detail, and may change in the future.
+```
+
+The BNS indexer implements the blockchain consensus rules and network protocols.
+Its main responsibility is to build up and replicate all of the name state. It does
+not have any public APIs of its own.
+
+The BNS API modules allows users and developers to resolve names via a RESTful
+interface. Resolution can be done with vanilla `curl` or `wget`.
+BNS applications should use the BNS API module for name resolution.
+They should not attempt to talk to a BNS indexer directly, because its API is not stable and is not meant
+for consumption by any other process except for the API module.
+
+Registering and managing names require generating and sending blockchain
+transactions, which requires running a BNS client. We provide two reference
+BNS clients:
+
+* The [Blockstack Browser](https://github.com/blockstack/blockstack-browser) gives users
+and developers a graphical UI to resolve, register and manage names. This is the recommended
+way to interact with BNS.
+* The Blockstack CLI gives developers low-level
+control over resolving, registering, and managing names.
+A new CLI that uses [blockstack.js](https://github.com/blockstack/blockstack.js)
+is under development, and will replace the existing CLI program.
+
+We recommend that new developers use the [Blockstack
+Browser](https://github.com/blockstack/blockstack-browser).
+
+Developers who want to make their own client programs that do not use
+the reference client library code should read the
+[BNS transaction wire format]({{ site.baseurl }}/core/wire-format.html) document for generating and
+sending their own transactions.
+
+The examples in this document focus on resolving names using `curl`. We refer
+the reader to client-specific documentation for registering and managing names.
diff --git a/_core/.svn/pristine/30/30e8eeea74a69fc676f1f45466d595c9637ffbed.svn-base b/_core/.svn/pristine/30/30e8eeea74a69fc676f1f45466d595c9637ffbed.svn-base
new file mode 100644
index 00000000..b9105255
--- /dev/null
+++ b/_core/.svn/pristine/30/30e8eeea74a69fc676f1f45466d595c9637ffbed.svn-base
@@ -0,0 +1,148 @@
+## What is the Blockstack ecosystem
+
+In the Blockstack ecosystem, users control their data and apps run on their devices. There
+are no middlemen, no passwords, no massive data silos to breach, and no services
+tracking us around the internet.
+
+The applications on blockstack are server-less and decentralized. Developers
+start by building a single-page application in Javascript, Then, instead of
+plugging the frontend into a centralized API, they plug into an API run by the
+user. Developers install a library called `blockstack.js` and don't have to
+worry about running servers, maintaining databases, or building out user
+management systems.
+
+Personal user APIs ship with the Blockstack app and handle everything from
+identity and authentication to data storage. Applications can request
+permissions from users and then gain read and write access to user resources.
+
+Data storage is simple and reliable and uses existing cloud infrastructure.
+Users connect with their Dropbox, Google Drive, S3, etc... and data is synced
+from their local device up to their cloud.
+
+Identity is user-controlled and utilizes the blockchain for secure management of
+keys, devices and usernames. When users login with apps, they are anonymous by
+default and use an app-specific key, but their full identity can be revealed and
+proven at any time. Keys are for signing and encryption and can be changed as
+devices need to be added or removed.
+
+Under the hood, Blockstack provides a decentralized domain name system (DNS),
+decentralized public key distribution system, and registry for apps and user
+identities.
+
+## What problems does Blockstack solve?
+
+Developers can now build Web applications where:
+
+- you own your data, not the application
+- you control where your data is stored
+- you control who can access your data
+
+Developers can now build Web applications where:
+
+- you don't have to deal with passwords
+- you don't have to host everyone's data
+- you don't have to run app-specific servers
+
+Right now, Web application users are "digital serfs" and applications are the "digital landlords". Users don't own their data; the app owns it. Users don't control where data gets stored; they can only store it on the application. Users don't control access to it; they only advise the application on how to control access (which the application can ignore).
+
+Blockstack applications solve both sets of problems. Users pick and choose highly-available storage providers like Dropbox or BitTorrent to host their data, and applications read it with the user's consent. Blockstack ensures that all data is signed and verified and (optionally) encrypted end-to-end, so users can treat storage providers like dumb hard drives: if you don't like yours, you can swap it out with a better one. Users can take their data with them if they leave the application, since it was never the application's in the first place.
+
+At the same time, developers are no longer on the hook for hosting user data. Since users bring their own storage and use public-key cryptography for authentication, applications don't have to store anything--there's nothing to steal when they get hacked. Moreover, many Web applications today can be re-factored so that everything happens client-side, obviating the need for running dedicated application servers.
+
+
+## What is a Blockstack ID?
+
+Blockstack IDs are usernames. Unlike normal Web app usernames, Blockstack IDs
+are usable *across every Blockstack app.* They fill a similar role to
+centralized single-signon services like Facebook or Google. However, you and
+only you control your Blockstack ID, and no one can track your logins.
+
+## How do I get a Blockstack ID?
+
+If you use the [Blockstack Browser]({{ site.baseurl }}/browser/browser-introduction.md) to create a
+new ID.
+
+## Why do I need a Blockstack ID?
+
+Blockstack IDs are used to discover where you are keeping your
+(publicly-readable) application data. For example, if `alice.id` wants to share
+a document with `bob.id`, then `bob.id`'s browser uses the Blockstack ID
+`alice.id` to look up where `alice.id` stored it.
+
+The technical descriptions of how and why this works are quite long.
+Please see the [Blockstack Naming Service]({{site.baseurl}}/core/naming/introduction.html)
+documentation for a full description.
+
+=
+
+## What components make ups the Blockstack ecosystem?
+
+The components that make up Blockstack do not have any central points of
+control.
+
+* The [Blockstack Naming Service]({{ site.baseurl }}/core/naming/introduction.html) runs on top of
+ the Bitcoin blockchain, which itself is decentralized. It binds Blockstack
+IDs to a small amount of on-chain data (usually a hash of off-chain data).
+* The [Atlas Peer Network]({{ site.baseurl }}/core/atlas/overview.html) stores chunks of data referenced by
+names in BNS. It operates under similar design principles to BitTorrent, and
+has no single points of failure. The network is self-healing---if a node
+crashes, it quickly recovers all of its state from its peers.
+* The [Gaia storage system](https://github.com/blockstack/gaia) lets users
+ choose where their application data gets hosted. Gaia reduces all storage
+systems---from cloud storage to peer-to-peer networks---to dumb, interchangeable
+hard drives. Users have maximum flexibility and control over their data in a
+way that is transparent to app developers.
+
+
+## Blockstack vs Ethereum
+
+Blockstack and Ethereum both strive to provide a decentralized application
+platform. Blockstack's design philosophy differs from Ethereum's design
+philosophy in that Blockstack emphasizes treating the blockchain as a "dumb
+ledger" with no special functionality or properties beyond a few bare minimum
+requirements. Instead, it strives to do everything off-chain---an application of the [end-to-end principle](https://en.wikipedia.org/wiki/End-to-end_principle).
+Most Blockstack applications do *not*
+interact with the blockchain, and instead interact with Blockstack
+infrastructure through client libraries and RESTful endpoints.
+This is evidenced by Blockstack's decision to implement its naming system (BNS), discovery and routing system
+(Atlas), and storage system (Gaia) as blockchain-agnostic components that can be
+ported from one blockchain to another.
+
+Ethereum takes the opposite approach. Ethereum dapps are expected to interface
+directly with on-chain smart contract logic, and are expected to host a
+non-trivial amount of state in the blockchain itself. This is necessary for
+them, because many Ethereum dapps' business logic is centered around the
+mechanics of an ERC20 token.
+
+Blockstack does not implement a smart contract system (yet), but it will soon
+implement a [native token](https://blockstack.com/distribution.pdf) that will be
+accessible to Blockstack applications.
+
+
+## What's the difference between Onename and Blockstack?
+
+Onename is the free Blockstack ID registrar run by Blockstack. It makes it easy to register your name and setup your profile. Once the name has been registered in Onename you can transfer it to a wallet you control, or leave it there and use it as you like.
+
+## How is Blockstack different from Namecoin?
+
+Blockstack DNS differs from Namecoin DNS in a few fundamental ways: blockchain layering, storage models, name pricing models, and incentives for miners. We wrote a post where you can learn more here: https://blockstack.org/docs/blockstack-vs-namecoin
+
+## I heard you guys were on Namecoin, what blockchain do you use now?
+
+We use the Bitcoin blockchain for our source of truth.
+
+## How long has the project been around?
+
+Work on the project started in late 2013. First public commits on the code are
+from Jan 2014. The first registrar for Blockstack was launched in March 2014 and
+the project has been growing since then.
+
+## Who started the project? Who maintains it?
+
+The project was started by two engineers from Princeton University. Muneeb Ali
+and Ryan Shea met at the Computer Science department at Princeton, where Muneeb
+was finishing his PhD and Ryan was running the enterprenurship club. In 2014,
+frustrated by the walled-gardens and security problems of the current internet
+they started working on a decentralized internet secured by blockchains. A full
+list of contributors can be found
+[here](https://github.com/blockstack/blockstack-core/graphs/contributors).
diff --git a/_core/.svn/pristine/32/32d12aa842ecc2c41d865c83ae91ed8c546c12e5.svn-base b/_core/.svn/pristine/32/32d12aa842ecc2c41d865c83ae91ed8c546c12e5.svn-base
new file mode 100644
index 00000000..feffd68f
--- /dev/null
+++ b/_core/.svn/pristine/32/32d12aa842ecc2c41d865c83ae91ed8c546c12e5.svn-base
@@ -0,0 +1,47 @@
+## Hardware and OS requirements
+
+* A 64-bit CPU running at at least 1 GHz is *highly* recommended (but not strictly required)
+* You will need ~250MB RAM and ~10 GB disk free. Do **not** attempt to use a network-attached disk for this.
+* You should have at least 30,000 inodes free in your filesystem. Unless you are using a very small VM image, you almost certainly have enough (you can check with `df -i`).
+* TCP port 6264 should be open and support bidirectional traffic. If you want to use SSL, then port 6263 should be open.
+* A reliable Internet connection of DSL-like quality or higher
+
+## Deployment
+### The Easy Way
+* Install from `pip`, source code, or Docker
+* Run `blockstack-core fast_sync`
+* Run `blockstack-core start`
+
+### The Less Easy Way
+* Install from `pip`, source code, or Docker
+* Run `blockstack-core start`
+* Wait a few days
+
+#### Best Practices for the Less Easy Way
+* Take a `blockstack-server.snapshots` database from a known-good node and pass `--expected_snapshots=/path/to/blockstack-server.snapshots`. This will force your bootstrapping node to verify that it reaches the same sequence of consensus hashes as it bootstraps (i.e. your node will detect any divergence from Blockstack's name history and abort early, instead of wasting your time).
+* Make sure you're in a position to leave the node online at 100% CPU use for the duration of its bootstrapping period
+
+### The Hard Way
+* Install `bitcoind` (version 0.16.x is recommended for now)
+* Start `bitcoind` as `bitcoind -daemon -txindex=1`
+* Wait for `bitcoind` to download the entire blockchain. This can take between 1 hour and 1 day.
+* Install `blockstack-core` from source, `pip`, or Docker
+* Run `blockstack-core configure` and enter your `bitcoind` node's IP address, port, RPC username, and RPC password when prompted
+* Run `blockstack-core start`
+* Wait a few days
+
+#### Best Practices for the Hard Way
+* You're going to need ~500 GB of space for the Bitcoin blockchain state
+* You can safely store its chain state on a network-attached disk, if you're doing this in a cloud-hosted environment
+* Your `bitcoind` host will need TCP:8332-8333 open for bidirectional traffic
+
+## Troubleshooting
+### The node stops responding to TCP:6264
+* Check `dmesg` for TCP SYN flooding. The solution here is to kill and restart the node.
+* To mitigate, install a rate-limiting proxy HTTP server in front of the node. We have a sample config for `nginx` [here](https://github.com/blockstack/atlas/blob/master/public_fleet/node/default).
+
+### No other Blockstack nodes contact my node
+* Verify that your IP address is publicly-routable, and that peers can communicate on TCP:6264
+
+### People are attacking my Bitcoin node
+* Stick an `nginx` reverse proxy in front of your `bitcoind` node, and use our [nginx](https://github.com/blockstack/atlas/tree/master/public_fleet/bitcoind) scripts to limit APi access to only the JSON-RPC methods Blockstack actually needs. Better yet, do what we do---build a statically-linked `bitcoind` binary from source that simply omits all of the RPC methods except the ones listed in the linked config file.
diff --git a/_core/.svn/pristine/35/356f4ca57dc37a04d4ab714f3c37297d5622a93c.svn-base b/_core/.svn/pristine/35/356f4ca57dc37a04d4ab714f3c37297d5622a93c.svn-base
new file mode 100644
index 00000000..c47fc26b
Binary files /dev/null and b/_core/.svn/pristine/35/356f4ca57dc37a04d4ab714f3c37297d5622a93c.svn-base differ
diff --git a/_core/.svn/pristine/37/3709e9f222f7bd179809b35707411b8b3f4970b7.svn-base b/_core/.svn/pristine/37/3709e9f222f7bd179809b35707411b8b3f4970b7.svn-base
new file mode 100644
index 00000000..ee9234b6
--- /dev/null
+++ b/_core/.svn/pristine/37/3709e9f222f7bd179809b35707411b8b3f4970b7.svn-base
@@ -0,0 +1,497 @@
+---
+layout: core
+permalink: /:collection/:path.html
+---
+# Bitcoin wire format
+{:.no_toc}
+
+This page is for organizations who want to be able to create and send name operation transactions to the blockchain(s) Blockstack supports.
+It describes the transaction formats for the Bitcoin blockchain.
+
+* TOC
+{:toc}
+
+## Transaction format
+
+Each Bitcoin transaction for Blockstack contains signatures from two sets of keys: the name owner, and the payer. The owner `scriptSig` and `scriptPubKey` fields are generated from the key(s) that own the given name. The payer `scriptSig` and `scriptPubKey` fields are used to *subsidize* the operation. The owner keys do not pay for any operations; the owner keys only control the minimum amount of BTC required to make the transaction standard. The payer keys only pay for the transaction's fees, and (when required) they pay the name fee.
+
+This construction is meant to allow the payer to be wholly separate from the owner. The principal that owns the name can fund their own transactions, or they can create a signed transaction that carries out the desired operation and request some other principal (e.g. a parent organization) to actually pay for and broadcast the transaction.
+
+The general transaction layout is as follows:
+
+| **Inputs** | **Outputs** |
+| ------------------------ | ----------------------- |
+| Owner scriptSig (1) | `OP_RETURN ` (2) |
+| Payment scriptSig | Owner scriptPubKey (3) |
+| Payment scriptSig... (4) |
+| ... (4) | ... (5) |
+
+(1) The owner `scriptSig` is *always* the first input.
+(2) The `OP_RETURN` script that describes the name operation is *always* the first output.
+(3) The owner `scriptPubKey` is *always* the second output.
+(4) The payer can use as many payment inputs as (s)he likes.
+(5) At most one output will be the "change" `scriptPubKey` for the payer.
+Different operations require different outputs.
+
+## Payload Format
+
+Each Blockstack transaction in Bitcoin describes the name operation within an `OP_RETURN` output. It encodes name ownership, name fees, and payments as `scriptPubKey` outputs. The specific operations are described below.
+
+Each `OP_RETURN` payload *always* starts with the two-byte string `id` (called the "magic" bytes in this document), followed by a one-byte `op` that describes the operation.
+
+### NAME_PREORDER
+
+Op: `?`
+
+Description: This transaction commits to the *hash* of a name. It is the first
+transaction of two transactions that must be sent to register a name in BNS.
+
+Example: [6730ae09574d5935ffabe3dd63a9341ea54fafae62fde36c27738e9ee9c4e889](https://www.blocktrail.com/BTC/tx/6730ae09574d5935ffabe3dd63a9341ea54fafae62fde36c27738e9ee9c4e889)
+
+`OP_RETURN` wire format:
+```
+ 0 2 3 23 39
+ |-----|--|--------------------------------------------------|--------------|
+ magic op hash_name(name.ns_id,script_pubkey,register_addr) consensus hash
+```
+
+Inputs:
+* Payment `scriptSig`'s
+
+Outputs:
+* `OP_RETURN` payload
+* Payment `scriptPubkey` script for change
+* `p2pkh` `scriptPubkey` to the burn address (0x00000000000000000000000000000000000000)
+
+Notes:
+* `register_addr` is a base58check-encoded `ripemd160(sha256(pubkey))` (i.e. an address). This address **must not** have been used before in the underlying blockchain.
+* `script_pubkey` is either a `p2pkh` or `p2sh` compiled Bitcoin script for the payer's address.
+
+### NAME_REGISTRATION
+
+Op: `:`
+
+Description: This transaction reveals the name whose hash was announced by a
+previous `NAME_PREORDER`. It is the second of two transactions that must be
+sent to register a name in BNS.
+
+Example: [55b8b42fc3e3d23cbc0f07d38edae6a451dfc512b770fd7903725f9e465b2925](https://www.blocktrail.com/BTC/tx/55b8b42fc3e3d23cbc0f07d38edae6a451dfc512b770fd7903725f9e465b2925)
+
+`OP_RETURN` wire format (2 variations allowed):
+
+Variation 1:
+```
+ 0 2 3 39
+ |----|--|-----------------------------|
+ magic op name.ns_id (37 bytes)
+```
+
+Variation 2:
+```
+ 0 2 3 39 59
+ |----|--|----------------------------------|-------------------|
+ magic op name.ns_id (37 bytes, 0-padded) value
+```
+
+Inputs:
+* Payer `scriptSig`'s
+
+Outputs:
+* `OP_RETURN` payload
+* `scriptPubkey` for the owner's address
+* `scriptPubkey` for the payer's change
+
+Notes:
+
+* Variation 1 simply registers the name. Variation 2 will register the name and
+set a name value simultaneously. This is used in practice to set a zone file
+hash for a name without the extra `NAME_UPDATE` transaction.
+* Both variations are supported. Variation 1 was designed for the time when
+ Bitcoin only supported 40-byte `OP_RETURN` outputs.
+
+### NAME_RENEWAL
+
+Op: `:`
+
+Description: This transaction renews a name in BNS. The name must still be
+registered and not expired, and owned by the transaction sender.
+
+Example: [e543211b18e5d29fd3de7c0242cb017115f6a22ad5c6d51cf39e2b87447b7e65](https://www.blocktrail.com/BTC/tx/e543211b18e5d29fd3de7c0242cb017115f6a22ad5c6d51cf39e2b87447b7e65)
+
+`OP_RETURN` wire format (2 variations allowed):
+
+Variation 1:
+```
+ 0 2 3 39
+ |----|--|-----------------------------|
+ magic op name.ns_id (37 bytes)
+```
+
+Variation 2:
+```
+ 0 2 3 39 59
+ |----|--|----------------------------------|-------------------|
+ magic op name.ns_id (37 bytes, 0-padded) value
+```
+
+Inputs:
+
+* Payer `scriptSig`'s
+
+Outputs:
+
+* `OP_RETURN` payload
+* `scriptPubkey` for the owner's addess. This can be a different address than
+ the current name owner (in which case, the name is renewed and transferred).
+* `scriptPubkey` for the payer's change
+* `scriptPubkey` for the burn address (to pay the name cost)
+
+Notes:
+
+* This transaction is identical to a `NAME_REGISTRATION`, except for the presence of the fourth output that pays for the name cost (to the burn address).
+* Variation 1 simply renews the name. Variation 2 will both renew the name and
+ set a new name value (in practice, the hash of a new zone file).
+* Both variations are supported. Variation 1 was designed for the time when
+ Bitcoin only supported 40-byte `OP_RETURN` outputs.
+* This operation can be used to transfer a name to a new address by setting the
+ second output (the first `scriptPubkey`) to be the `scriptPubkey` of the new
+ owner key.
+
+### NAME_UPDATE
+
+Op: `+`
+
+Description: This transaction sets the name state for a name to the given
+`value`. In practice, this is used to announce new DNS zone file hashes to the [Atlas
+network]({{ site.baseurl }}/core/atlas/overview.html).
+
+Example: [e2029990fa75e9fc642f149dad196ac6b64b9c4a6db254f23a580b7508fc34d7](https://www.blocktrail.com/BTC/tx/e2029990fa75e9fc642f149dad196ac6b64b9c4a6db254f23a580b7508fc34d7)
+
+`OP_RETURN` wire format:
+```
+ 0 2 3 19 39
+ |-----|--|-----------------------------------|-----------------------|
+ magic op hash128(name.ns_id,consensus hash) zone file hash
+```
+
+Note that `hash128(name.ns_id, consensus hash)` is the first 16 bytes of a SHA256 hash over the name concatenated to the hexadecimal string of the consensus hash (not the bytes corresponding to that hex string).
+See the [Method Glossary](#method-glossary) below.
+
+Example: `hash128("jude.id" + "8d8762c37d82360b84cf4d87f32f7754") == "d1062edb9ec9c85ad1aca6d37f2f5793"`.
+
+Inputs:
+* owner `scriptSig`
+* payment `scriptSig`'s
+
+Outputs:
+* `OP_RETURN` payload
+* owner's `scriptPubkey`
+* payment `scriptPubkey` change
+
+### NAME_TRANSFER
+
+Op: `>`
+
+Description: This transaction changes the public key hash that owns the name in
+BNS.
+
+Example: [7a0a3bb7d39b89c3638abc369c85b5c028d0a55d7804ba1953ff19b0125f3c24](https://www.blocktrail.com/BTC/tx/7a0a3bb7d39b89c3638abc369c85b5c028d0a55d7804ba1953ff19b0125f3c24)
+
+`OP_RETURN` wire format:
+```
+ 0 2 3 4 20 36
+ |-----|--|----|-------------------|---------------|
+ magic op keep hash128(name.ns_id) consensus hash
+ data?
+```
+
+Inputs:
+
+* Owner `scriptSig`
+* Payment `scriptSig`'s
+
+Outputs:
+
+* `OP_RETURN` payload
+* new name owner's `scriptPubkey`
+* old name owner's `scriptPubkey`
+* payment `scriptPubkey` change
+
+Notes:
+
+* The `keep data?` byte controls whether or not the name's 20-byte value is preserved. This value is either `>` to preserve it, or `~` to delete it.
+
+### NAME_REVOKE
+
+Op: `~`
+
+Description: This transaction destroys a registered name. Its name state value
+in BNS will be cleared, and no further transactions will be able to affect the
+name until it expires (if its namespace allows it to expire at all).
+
+Example: [eb2e84a45cf411e528185a98cd5fb45ed349843a83d39fd4dff2de47adad8c8f](https://www.blocktrail.com/BTC/tx/eb2e84a45cf411e528185a98cd5fb45ed349843a83d39fd4dff2de47adad8c8f)
+
+`OP_RETURN` wire format:
+```
+ 0 2 3 39
+ |----|--|-----------------------------|
+ magic op name.ns_id (37 bytes)
+```
+
+Inputs:
+
+* owner `scriptSig`
+* payment `scriptSig`'s
+
+Outputs:
+
+* `OP_RETURN` payload
+* owner `scriptPubkey`
+* payment `scriptPubkey` change
+
+### ANNOUNCE
+
+Op: `#`
+
+Description: This transaction does not affect any names in BNS, but it allows a
+user to send a message to other BNS nodes. In order for the message to be
+received, the following must be true:
+
+* The sender must have a BNS name
+* The BNS nodes must list the sender's BNS name as being a "trusted message
+ sender"
+* The message must have already been propagated through the [Atlas
+ network]({{ site.baseurl }}/core/atlas/overview.html). This transaction references it by content hash.
+
+`OP_RETURN` wire format:
+
+```
+ 0 2 3 23
+ |----|--|-----------------------------|
+ magic op ripemd160(sha256(message))
+```
+
+Inputs:
+
+* The payer `scriptSig`'s
+
+Outputs:
+
+* `OP_RETURN` payload
+* change `scriptPubKey`
+
+Notes:
+
+* The payer key should be an owner key for an existing name, since Blockstack users can subscribe to announcements from specific name-owners.
+
+### NAMESPACE_PREORDER
+
+Op: `*`
+
+Description: This transaction announces the *hash* of a new namespace. It is the
+first of three transactions that must be sent to create a namespace.
+
+Example: [5f00b8e609821edd6f3369ee4ee86e03ea34b890e242236cdb66ef6c9c6a1b28](https://www.blocktrail.com/BTC/tx/5f00b8e609821edd6f3369ee4ee86e03ea34b890e242236cdb66ef6c9c6a1b28)
+
+`OP_RETURN` wire format:
+```
+ 0 2 3 23 39
+ |-----|---|-----------------------------------------|----------------|
+ magic op hash_name(ns_id,script_pubkey,reveal_addr) consensus hash
+```
+
+Inputs:
+
+* Namespace payer `scriptSig`
+
+Outputs:
+
+* `OP_RETURN` payload
+* Namespace payer `scriptPubkey` change address
+* `p2pkh` script to the burn address `1111111111111111111114oLvT2`, whose public key hash is 0x00000000000000000000000000000000
+
+Notes:
+
+* The `reveal_addr` field is the address of the namespace revealer public key. The revealer private key will be used to generate `NAME_IMPORT` transactions.
+
+### NAMESPACE_REVEAL
+
+Op: `&`
+
+Description: This transaction reveals the namespace ID and namespace rules
+for a previously-anounced namespace hash (sent by a previous `NAMESPACE_PREORDER`).
+
+Example: [ab54b1c1dd5332dc86b24ca2f88b8ca0068485edf0c322416d104c5b84133a32](https://www.blocktrail.com/BTC/tx/ab54b1c1dd5332dc86b24ca2f88b8ca0068485edf0c322416d104c5b84133a32)
+
+`OP_RETURN` wire format:
+```
+ 0 2 3 7 8 9 10 11 12 13 14 15 16 17 18 20 39
+ |-----|---|--------|-----|-----|----|----|----|----|----|-----|-----|-----|--------|----------|-------------------------|
+ magic op life coeff. base 1-2 3-4 5-6 7-8 9-10 11-12 13-14 15-16 nonalpha version namespace ID
+ bucket exponents no-vowel
+ discounts
+```
+
+Inputs:
+
+* Namespace payer `scriptSig`s
+
+Outputs:
+
+* `OP_RETURN` payload
+* namespace revealer `scriptPubkey`
+* namespace payer change `scriptPubkey`
+
+Notes:
+
+* This transaction must be sent within 1 day of the `NAMESPACE_PREORDER`
+* The second output (with the namespace revealer) **must** be a `p2pkh` script
+* The address of the second output **must** be the `reveal_addr` in the `NAMESPACE_PREORDER`
+
+Pricing:
+
+The rules for a namespace are as follows:
+
+ * a name can fall into one of 16 buckets, measured by length. Bucket 16 incorporates all names at least 16 characters long.
+ * the pricing structure applies a multiplicative penalty for having numeric characters, or punctuation characters.
+ * the price of a name in a bucket is ((coeff) * (base) ^ (bucket exponent)) / ((numeric discount multiplier) * (punctuation discount multiplier))
+
+Example:
+* base = 10
+* coeff = 2
+* nonalpha discount: 10
+* no-vowel discount: 10
+* buckets 1, 2: 9
+* buckets 3, 4, 5, 6: 8
+* buckets 7, 8, 9, 10, 11, 12, 13, 14: 7
+* buckets 15, 16+:
+
+With the above example configuration, the following are true:
+
+* The price of "john" would be 2 * 10^8, since "john" falls into bucket 4 and has no punctuation or numerics.
+* The price of "john1" would be 2 * 10^6, since "john1" falls into bucket 5 but has a number (and thus receives a 10x discount)
+* The price of "john_1" would be 2 * 10^6, since "john_1" falls into bucket 6 but has a number and punctuation (and thus receives a 10x discount)
+* The price of "j0hn_1" would be 2 * 10^5, since "j0hn_1" falls into bucket 6 but has a number and punctuation and lacks vowels (and thus receives a 100x discount)
+
+
+### NAME_IMPORT
+
+Op: `;`
+
+Description: This transaction registers a name and some name state into a
+namespace that has been revealed, but not been launched. Only the namespace
+creator can import names. See the [namespace creation section]({{ site.baseurl }}/core/naming/namespace.html) for details.
+
+Example: [c698ac4b4a61c90b2c93dababde867dea359f971e2efcf415c37c9a4d9c4f312](https://www.blocktrail.com/BTC/tx/c698ac4b4a61c90b2c93dababde867dea359f971e2efcf415c37c9a4d9c4f312)
+
+`OP_RETURN` wire format:
+```
+ 0 2 3 39
+ |----|--|-----------------------------|
+ magic op name.ns_id (37 bytes)
+```
+
+Inputs:
+
+* The namespace reveal `scriptSig` (with the namespace revealer's public key), or one of its first 300 extended public keys
+* Any payment inputs
+
+Outputs:
+
+* `OP_RETURN` payload
+* recipient `scriptPubKey`
+* zone file hash (using the 20-byte hash in a standard `p2pkh` script)
+* payment change `scriptPubKey`
+
+Notes:
+
+* These transactions can only be sent between the `NAMESPACE_REVEAL` and `NAMESPACE_READY`.
+* The first `NAME_IMPORT` transaction **must** have a `scriptSig` input that matches the `NAMESPACE_REVEAL`'s second output (i.e. the reveal output).
+* Any subsequent `NAME_IMPORT` transactions **may** have a `scriptSig` input whose public key is one of the first 300 extended public keys from the `NAMESPACE_REVEAL`'s `scriptSig` public key.
+
+### NAMESPACE_READY
+
+Op: `!`
+
+Description: This transaction launches a namesapce. Only the namespace creator
+can send this transaction. Once sent, anyone can register names in the
+namespace.
+
+Example: [2bf9a97e3081886f96c4def36d99a677059fafdbd6bdb6d626c0608a1e286032](https://www.blocktrail.com/BTC/tx/2bf9a97e3081886f96c4def36d99a677059fafdbd6bdb6d626c0608a1e286032)
+
+`OP_RETURN` wire format:
+```
+
+ 0 2 3 4 23
+ |-----|--|--|------------|
+ magic op . ns_id
+```
+
+Inputs:
+* Namespace revealer's `scriptSig`s
+
+Outputs:
+* `OP_RETURN` payload
+* Change output to the namespace revealer's `p2pkh` script
+
+Notes:
+* This transaction must be sent within 1 year of the corresponding `NAMESPACE_REVEAL` to be accepted.
+
+## Method Glossary
+
+Some hashing primitives are used to construct the wire-format representation of each name operation. They are enumerated here:
+
+```
+B40_REGEX = '^[a-z0-9\-_.+]*$'
+
+def is_b40(s):
+ return isinstance(s, str) and re.match(B40_REGEX, s) is not None
+
+def b40_to_bin(s):
+ if not is_b40(s):
+ raise ValueError('{} must only contain characters in the b40 char set'.format(s))
+ return unhexlify(charset_to_hex(s, B40_CHARS))
+
+def hexpad(x):
+ return ('0' * (len(x) % 2)) + x
+
+def charset_to_hex(s, original_charset):
+ return hexpad(change_charset(s, original_charset, B16_CHARS))
+
+def bin_hash160(s, hex_format=False):
+ """ s is in hex or binary format
+ """
+ if hex_format and is_hex(s):
+ s = unhexlify(s)
+ return hashlib.new('ripemd160', bin_sha256(s)).digest()
+
+def hex_hash160(s, hex_format=False):
+ """ s is in hex or binary format
+ """
+ if hex_format and is_hex(s):
+ s = unhexlify(s)
+ return hexlify(bin_hash160(s))
+
+def hash_name(name, script_pubkey, register_addr=None):
+ """
+ Generate the hash over a name and hex-string script pubkey.
+ Returns the hex-encoded string RIPEMD160(SHA256(x)), where
+ x is the byte string composed of the concatenation of the
+ binary
+ """
+ bin_name = b40_to_bin(name)
+ name_and_pubkey = bin_name + unhexlify(script_pubkey)
+
+ if register_addr is not None:
+ name_and_pubkey += str(register_addr)
+
+ # make hex-encoded hash
+ return hex_hash160(name_and_pubkey)
+
+def hash128(data):
+ """
+ Hash a string of data by taking its 256-bit sha256 and truncating it to the
+ first 16 bytes
+ """
+ return hexlify(bin_sha256(data)[0:16])
+```
diff --git a/_core/.svn/pristine/3e/3e8c6e5b72720c73156d03e369f68a6f4109642b.svn-base b/_core/.svn/pristine/3e/3e8c6e5b72720c73156d03e369f68a6f4109642b.svn-base
new file mode 100644
index 00000000..5bdcd3df
--- /dev/null
+++ b/_core/.svn/pristine/3e/3e8c6e5b72720c73156d03e369f68a6f4109642b.svn-base
@@ -0,0 +1,5 @@
+# About this `docs` directory
+
+The contents of this directory acts as source for material for
+[docs.blockstack.org](https://docs.blockstack.org/), a searchabe documentation
+site for all things Blockstack.
diff --git a/_core/.svn/pristine/44/445fd35727edafa78c0b0f932cde9d384dfde8e2.svn-base b/_core/.svn/pristine/44/445fd35727edafa78c0b0f932cde9d384dfde8e2.svn-base
new file mode 100644
index 00000000..b48072b7
Binary files /dev/null and b/_core/.svn/pristine/44/445fd35727edafa78c0b0f932cde9d384dfde8e2.svn-base differ
diff --git a/_core/.svn/pristine/57/57fadd109171f8dff405bd4cadb643b35a0311a6.svn-base b/_core/.svn/pristine/57/57fadd109171f8dff405bd4cadb643b35a0311a6.svn-base
new file mode 100644
index 00000000..44eae4aa
--- /dev/null
+++ b/_core/.svn/pristine/57/57fadd109171f8dff405bd4cadb643b35a0311a6.svn-base
@@ -0,0 +1,45 @@
+---
+layout: core
+permalink: /:collection/:path.html
+---
+# Installing Memcached
+
+The Blockstack API optionally uses memcached and pylibmc for scaling read-only
+calls. If you want to enable this functionality then you should have memcached
+running locally.
+
+### Memcached on Debian & Ubuntu:
+
+```
+$ sudo apt-get install -y python-dev libmemcached-dev zlib1g-dev
+$ pip install pylibmc
+```
+
+### Memcached on macOS:
+
+Easiest way to install memcached on macOS is by using [Homebrew](https://brew.sh/).
+
+After installing Homebrew:
+
+```
+$ brew install memcached
+$ brew install libmemcached
+$ pip install pylibmc --install-option="--with-libmemcached=/usr/local/Cellar/libmemcached/1.0.18_1/"
+```
+
+After installing, you can start memcached and check if it's running properly:
+
+```
+$ memcached -d
+$ echo stats | nc localhost 11211
+```
+
+### Memcached on Heroku
+
+To deploy on Heroku:
+
+```bash
+$ heroku create
+$ heroku addons:add memcachedcloud
+$ git push heroku master
+```
diff --git a/_core/.svn/pristine/64/645412870ae7c64119817224eab42e07e531e579.svn-base b/_core/.svn/pristine/64/645412870ae7c64119817224eab42e07e531e579.svn-base
new file mode 100644
index 00000000..ddc54690
--- /dev/null
+++ b/_core/.svn/pristine/64/645412870ae7c64119817224eab42e07e531e579.svn-base
@@ -0,0 +1,357 @@
+mixin TryMe(action)
+ //- Give a "try-me" link for the public api endpoint
+ - var myUri = action.uriTemplate
+ - action.parameters.forEach( function (x) { myUri = myUri.replace( "{" + x.name + "}", x.example) } )
+ .title
+ strong
+ h4
+ div
+ div
+ span.method(class="badge get",style="float:left")
+ a.method(href=myUri, style="color:rgb(51, 122, 183);font-size:12pt")
+ = "Try It!"
+ |
+ p
+ div
+ |
+
+mixin Badge(method)
+ //- Draw a badge for a given HTTP method
+ case method
+ when 'GET'
+ span.badge.get: i.fa.fa-arrow-down
+ when 'HEAD'
+ span.badge.head: i.fa.fa-info-circle
+ when 'OPTIONS'
+ span.badge.options: i.fa.fa-dot-circle-o
+ when 'POST'
+ span.badge.post: i.fa.fa-plus
+ when 'PUT'
+ span.badge.put: i.fa.fa-pencil
+ when 'PATCH'
+ span.badge.patch: i.fa.fa-pencil
+ when 'DELETE'
+ span.badge.delete: i.fa.fa-times
+ default
+ span.badge: i.fa.fa-dot-circle-o
+
+mixin Nav(onlyPublic)
+ //- Draw a navigation bar, which includes links to individual
+ //- resources and actions.
+ nav
+ if self.api.navItems && self.api.navItems.length
+ .resource-group
+ .heading
+ .chevron
+ i.open.fa.fa-angle-down
+ a(href='#top') Overview
+ .collapse-content
+ ul: each item in self.api.navItems
+ li
+ a(href=item[1])!= item[0]
+ - if (onlyPublic){
+ - myGroups = self.api.resourceGroups.filter( filter_public_resourcegroups )
+ - }else{
+ - myGroups = self.api.resourceGroups.filter( filter_core_resourcegroups )
+ - }
+ each resourceGroup in myGroups || []
+ .resource-group
+ .heading
+ .chevron
+ i.open.fa.fa-angle-down
+ a(href=resourceGroup.elementLink)!= resourceGroup.name || 'Resource Group'
+ .collapse-content
+ ul
+ each item in resourceGroup.navItems || []
+ li
+ a(href=item[1])!= item[0]
+ - if (onlyPublic){
+ - myResources = resourceGroup.resources.filter( filter_public_resources )
+ - }else{
+ - myResources = resourceGroup.resources.filter( filter_core_resources )
+ - }
+ each resource in myResources || []
+ li
+ - if (onlyPublic){
+ - myActions = resource.actions.filter( filter_public_actions )
+ - }else{
+ - myActions = resource.actions.filter( filter_core_actions )
+ - }
+ if !self.condenseNav || (myActions.length != 1)
+ a(href=resource.elementLink)!= resource.name || 'Resource'
+ ul: each action in myActions || []
+ li: a(href=resource.elementLink)
+ +Badge(action.method)
+ != action.name || action.method + ' ' + (action.attributes && action.attributes.uriTemplate || resource.uriTemplate)
+ else
+ - var action = myActions[0]
+ a(href=resource.elementLink)
+ +Badge(action.method)
+ != action.name || resource.name || action.method + ' ' + (action.attributes && action.attributes.uriTemplate || resource.uriTemplate)
+ //- Link to the API hostname, e.g. api.yourcompany.com
+ each meta in self.api.metadata || {}
+ if meta.name == 'HOST'
+ p(style="text-align: center; word-wrap: break-word;")
+ a(href=meta.value)= meta.value
+
+mixin Parameters(params)
+ //- Draw a definition list of parameter names, types, defaults,
+ //- examples and descriptions.
+ .title
+ strong URI Parameters
+ .collapse-button.show
+ span.close Hide
+ span.open Show
+ .collapse-content
+ dl.inner: each param in params || []
+ dt= self.urldec(param.name)
+ dd
+ code= param.type || 'string'
+ |
+ if param.required
+ span.required (required)
+ else
+ span (optional)
+ |
+ if param.default
+ span.text-info.default
+ strong Default:
+ span= param.default
+ |
+ if param.example
+ span.text-muted.example
+ strong Example:
+ span= param.example
+ != self.markdown(param.description)
+ if param.values.length
+ p.choices
+ strong Choices:
+ each value in param.values
+ code= self.urldec(value.value)
+ = ' '
+
+mixin RequestResponse(title, request, collapse)
+ .title
+ strong
+ = title
+ if request.name
+ |
+ code= request.name
+ if collapse && request.hasContent
+ .collapse-button
+ span.close Hide
+ span.open Show
+ +RequestResponseBody(request, collapse)
+
+mixin RequestResponseBody(request, collapse, showBlank)
+ if request.hasContent || showBlank
+ div(class=collapse ? 'collapse-content' : ''): .inner
+ if request.description
+ .description!= self.markdown(request.description)
+
+ if Object.keys(request.headers).length
+ h5 Headers
+ pre: code
+ each item, index in request.headers
+ != self.highlight(item.name + ': ' + item.value, 'http')
+ if index < request.headers.length - 1
+ br
+ div(style="height: 1px;")
+ if request.body
+ h5 Body
+ pre: code
+ != self.highlight(request.body, null, ['json', 'yaml', 'xml', 'javascript'])
+ div(style="height: 1px;")
+ if request.schema
+ h5 Schema
+ pre: code
+ != self.highlight(request.schema, null, ['json', 'yaml', 'xml'])
+ div(style="height: 1px;")
+ if !request.hasContent
+ .description.text-muted This response has no content.
+ div(style="height: 1px;")
+
+mixin Examples(resourceGroup, resource, action)
+ each example in action.examples
+ each request in example.requests
+ +RequestResponse('Request', request, true)
+ each response in example.responses
+ +RequestResponse('Response', response, true)
+
+mixin Content()
+ //- Page header and API description
+ header
+ h1#top!= self.api.name || 'API Documentation'
+
+ if self.api.descriptionHtml
+ != self.api.descriptionHtml
+
+ //- Loop through and display information about all the resource
+ //- groups, resources, and actions.
+ each resourceGroup in self.api.resourceGroups || []
+ section.resource-group(id=resourceGroup.elementId)
+ h2.group-heading
+ != resourceGroup.name || 'Resource Group'
+ = " "
+ a.permalink(href=resourceGroup.elementLink) ¶
+ if resourceGroup.descriptionHtml
+ != resourceGroup.descriptionHtml
+
+ each resource in resourceGroup.resources || []
+ .resource(id=resource.elementId)
+ h3.resource-heading
+ != resource.name || ((resource.actions[0] != null) && resource.actions[0].name) || 'Resource'
+ = " "
+ a.permalink(href=resource.elementLink) ¶
+ if resource.description
+ != self.markdown(resource.description)
+
+ each action in resource.actions || []
+ .action(class=action.methodLower, id=action.elementId)
+ h4.action-heading
+ .name!= action.name
+ a.method(class=action.methodLower, href=action.elementLink)
+ = action.method
+ code.uri= self.urldec(action.uriTemplate)
+ if action.description
+ != self.markdown(action.description)
+
+ h4 Example URI
+ .definition
+ span.method(class=action.methodLower)= action.method
+ |
+ span.uri
+ span.hostname= self.api.host
+ != action.colorizedUriTemplate
+
+ //- A list of sub-sections for parameters, requests
+ //- and responses.
+ if action.parameters.length
+ +Parameters(action.parameters)
+ if action.examples
+ +Examples(resourceGroup, resource, action)
+
+- function filter_public_actions(x){
+- return (x.description.includes('+ Public Endpoint') || x.description.includes('+ Public Only Endpoint'))
+- }
+- function filter_public_resources(x){
+- return (x.actions.filter( filter_public_actions ).length > 0)
+- }
+- function filter_public_resourcegroups(x){
+- return (x.resources.filter( filter_public_resources ).length > 0)
+- }
+- function filter_core_actions(x){
+- return !(x.description.includes('+ Public Only Endpoint'))
+- }
+- function filter_core_resources(x){
+- return (x.actions.filter( filter_core_actions ).length > 0)
+- }
+- function filter_core_resourcegroups(x){
+- return (x.resources.filter( filter_core_resources ).length > 0)
+- }
+
+mixin ContentTriple(onlyPublic, descriptionHtml)
+
+ .right
+ h5 API Endpoint
+ a(href=self.api.host)= self.api.host
+ .middle
+ if descriptionHtml
+ != descriptionHtml
+
+ //- Loop through and display information about all the resource
+ //- groups, resources, and actions.
+ - if (onlyPublic){
+ - myGroups = self.api.resourceGroups.filter( filter_public_resourcegroups )
+ - }else{
+ - myGroups = self.api.resourceGroups.filter( filter_core_resourcegroups )
+ - }
+ each resourceGroup in myGroups || []
+ .middle
+ section.resource-group(id=resourceGroup.elementId)
+ h2.group-heading
+ != resourceGroup.name || 'Resource Group'
+ = " "
+ a.permalink(href=resourceGroup.elementLink) ¶
+ if resourceGroup.descriptionHtml
+ != resourceGroup.descriptionHtml
+
+ - if (onlyPublic){
+ - myResources = resourceGroup.resources.filter( filter_public_resources )
+ - }else{
+ - myResources = resourceGroup.resources.filter( filter_core_resources )
+ - }
+ each resource in myResources || []
+ if resource.public != null
+ .middle
+ .resource(id=resource.elementId)
+ a.permalink(href=resource.elementLink)
+ h3.resource-heading
+ != resource.name || ((resource.actions[0] != null) && resource.actions[0].name) || 'Resource'
+ = " "
+ ¶
+ if resource.description
+ != self.markdown(resource.description)
+
+ - if (onlyPublic){
+ - myActions = resource.actions.filter( filter_public_actions )
+ - }else{
+ - myActions = resource.actions.filter( filter_core_actions )
+ - }
+ each action in myActions || []
+ if action.examples
+ .right
+ .definition
+ span.method(class=action.methodLower)= action.method
+ |
+ span.uri
+ span.hostname= self.api.host
+ != action.colorizedUriTemplate
+ .tabs
+ if action.hasRequest
+ .example-names
+ span Requests
+ - var requestCount = 0
+ each example in action.examples
+ each request in example.requests
+ - requestCount++
+ span.tab-button= request.name || 'example ' + requestCount
+ each example in action.examples
+ each request in example.requests
+ .tab
+ +RequestResponseBody(request, false, true)
+ .tabs
+ .example-names
+ span Responses
+ each response in example.responses
+ span.tab-button= response.name
+ each response in example.responses
+ .tab
+ +RequestResponseBody(response, false, true)
+ else
+ each example in action.examples
+ .tabs
+ .example-names
+ span Responses
+ each response in example.responses
+ span.tab-button= response.name
+ each response in example.responses
+ .tab
+ +RequestResponseBody(response, false, true)
+ .middle
+ .action(class=action.methodLower, id=action.elementId)
+ h4.action-heading
+ .name!= action.name
+ a.method(class=action.methodLower, href=action.elementLink)
+ = action.method
+ code.uri= self.urldec(action.uriTemplate)
+ if action.description
+ != self.markdown(action.description)
+
+ //- A list of sub-sections for parameters, requests
+ //- and responses.
+ if action.parameters.length
+ +Parameters(action.parameters)
+ if onlyPublic
+ +TryMe(action)
+ hr.split
diff --git a/_core/.svn/pristine/66/669be53b5b33a93ddd84205629718e2fd224a628.svn-base b/_core/.svn/pristine/66/669be53b5b33a93ddd84205629718e2fd224a628.svn-base
new file mode 100644
index 00000000..0e01f0f5
--- /dev/null
+++ b/_core/.svn/pristine/66/669be53b5b33a93ddd84205629718e2fd224a628.svn-base
@@ -0,0 +1,249 @@
+---
+layout: core
+permalink: /:collection/:path.html
+---
+# BNS Subdomains
+
+{:.no_toc}
+
+This section explains BNS subdomains and provides instructions for methods
+you can use to work with them. The following topics are included:
+
+* TOC
+{:toc}
+
+# Overview of subdomains
+
+BNS names are strongly-owned because the owner of its private key can generate
+valid transactions that update its zone file hash and owner. However, this comes at the
+cost of requiring a name owner to pay for the underlying transaction in the
+blockchain. Moreover, this approach limits the rate of BNS name registrations
+and operations to the underlying blockchain's transaction bandwidth.
+
+BNS overcomes this with subdomains. A **BNS subdomain** is a type of BNS name whose state
+and owner are stored outside of the blockchain, but whose existence and
+operation history are anchored to the
+blockchain. In the example table in the [Resolving BNS
+Names](#resolving-bns-names) section, the names `cicero.res_publica.id` and
+`podsaveamerica.verified.podcast` are subdomains.
+
+Like their on-chain counterparts, subdomains are globally
+unique, strongly-owned, and human-readable. BNS gives them their own name state
+and public keys.
+
+Unlike on-chain names, subdomains can be created and managed
+cheaply, because they are broadcast to the
+BNS network in batches. A single blockchain transaction can send up to 120
+subdomain operations.
+
+This is achieved by storing subdomain records in the [Atlas Network]({{ site.baseurl }}/core/atlas/overview.html).
+An on-chain name owner broadcasts subdomain operations by encoding them as
+`TXT` records within a DNS zone file. To broadcast the zone file,
+the name owner sets the new zone file hash with a `NAME_UPDATE` transaction and
+replicates the zone file via Atlas. This, in turn, replicates all subdomain
+operations it contains, and anchors the set of subdomain operations to
+an on-chain transaction. The BNS node's consensus rules ensure that only
+valid subdomain operations from *valid* `NAME_UPDATE` transactions will ever be
+stored.
+
+For example, the name `verified.podcast` once wrote the zone file hash `247121450ca0e9af45e85a82e61cd525cd7ba023`,
+which is the hash of the following zone file:
+
+```bash
+$ curl -sL https://core.blockstack.org/v1/names/verified.podcast/zonefile/247121450ca0e9af45e85a82e61cd525cd7ba023 | jq -r '.zonefile'
+$ORIGIN verified.podcast
+$TTL 3600
+1yeardaily TXT "owner=1MwPD6dH4fE3gQ9mCov81L1DEQWT7E85qH" "seqn=0" "parts=1" "zf0=JE9SSUdJTiAxeWVhcmRhaWx5CiRUVEwgMzYwMApfaHR0cC5fdGNwIFVSSSAxMCAxICJodHRwczovL3BoLmRvdHBvZGNhc3QuY28vMXllYXJkYWlseS9oZWFkLmpzb24iCg=="
+2dopequeens TXT "owner=1MwPD6dH4fE3gQ9mCov81L1DEQWT7E85qH" "seqn=0" "parts=1" "zf0=JE9SSUdJTiAyZG9wZXF1ZWVucwokVFRMIDM2MDAKX2h0dHAuX3RjcCBVUkkgMTAgMSAiaHR0cHM6Ly9waC5kb3Rwb2RjYXN0LmNvLzJkb3BlcXVlZW5zL2hlYWQuanNvbiIK"
+10happier TXT "owner=1MwPD6dH4fE3gQ9mCov81L1DEQWT7E85qH" "seqn=0" "parts=1" "zf0=JE9SSUdJTiAxMGhhcHBpZXIKJFRUTCAzNjAwCl9odHRwLl90Y3AgVVJJIDEwIDEgImh0dHBzOi8vcGguZG90cG9kY2FzdC5jby8xMGhhcHBpZXIvaGVhZC5qc29uIgo="
+31thoughts TXT "owner=1MwPD6dH4fE3gQ9mCov81L1DEQWT7E85qH" "seqn=0" "parts=1" "zf0=JE9SSUdJTiAzMXRob3VnaHRzCiRUVEwgMzYwMApfaHR0cC5fdGNwIFVSSSAxMCAxICJodHRwczovL3BoLmRvdHBvZGNhc3QuY28vMzF0aG91Z2h0cy9oZWFkLmpzb24iCg=="
+359 TXT "owner=1MwPD6dH4fE3gQ9mCov81L1DEQWT7E85qH" "seqn=0" "parts=1" "zf0=JE9SSUdJTiAzNTkKJFRUTCAzNjAwCl9odHRwLl90Y3AgVVJJIDEwIDEgImh0dHBzOi8vcGguZG90cG9kY2FzdC5jby8zNTkvaGVhZC5qc29uIgo="
+30for30 TXT "owner=1MwPD6dH4fE3gQ9mCov81L1DEQWT7E85qH" "seqn=0" "parts=1" "zf0=JE9SSUdJTiAzMGZvcjMwCiRUVEwgMzYwMApfaHR0cC5fdGNwIFVSSSAxMCAxICJodHRwczovL3BoLmRvdHBvZGNhc3QuY28vMzBmb3IzMC9oZWFkLmpzb24iCg=="
+onea TXT "owner=1MwPD6dH4fE3gQ9mCov81L1DEQWT7E85qH" "seqn=0" "parts=1" "zf0=JE9SSUdJTiBvbmVhCiRUVEwgMzYwMApfaHR0cC5fdGNwIFVSSSAxMCAxICJodHRwczovL3BoLmRvdHBvZGNhc3QuY28vb25lYS9oZWFkLmpzb24iCg=="
+10minuteteacher TXT "owner=1MwPD6dH4fE3gQ9mCov81L1DEQWT7E85qH" "seqn=0" "parts=1" "zf0=JE9SSUdJTiAxMG1pbnV0ZXRlYWNoZXIKJFRUTCAzNjAwCl9odHRwLl90Y3AgVVJJIDEwIDEgImh0dHBzOi8vcGguZG90cG9kY2FzdC5jby8xMG1pbnV0ZXRlYWNoZXIvaGVhZC5qc29uIgo="
+36questionsthepodcastmusical TXT "owner=1MwPD6dH4fE3gQ9mCov81L1DEQWT7E85qH" "seqn=0" "parts=1" "zf0=JE9SSUdJTiAzNnF1ZXN0aW9uc3RoZXBvZGNhc3RtdXNpY2FsCiRUVEwgMzYwMApfaHR0cC5fdGNwIFVSSSAxMCAxICJodHRwczovL3BoLmRvdHBvZGNhc3QuY28vMzZxdWVzdGlvbnN0aGVwb2RjYXN0bXVzaWNhbC9oZWFkLmpzb24iCg=="
+_http._tcp URI 10 1 "https://dotpodcast.co/"
+```
+
+Each `TXT` record in this zone file encodes a subdomain-creation.
+For example, `1yeardaily.verified.podcast` resolves to:
+
+```bash
+$ curl https://core.blockstack.org/v1/names/1yeardaily.verified.podcast
+{
+ "address": "1MwPD6dH4fE3gQ9mCov81L1DEQWT7E85qH",
+ "blockchain": "bitcoin",
+ "last_txid": "d87a22ebab3455b7399bfef8a41791935f94bc97aee55967edd5a87f22cce339",
+ "status": "registered_subdomain",
+ "zonefile_hash": "e7acc97fd42c48ed94fd4d41f674eddbee5557e3",
+ "zonefile_txt": "$ORIGIN 1yeardaily\n$TTL 3600\n_http._tcp URI 10 1 \"https://ph.dotpodcast.co/1yeardaily/head.json\"\n"
+}
+```
+
+This information was extracted from the `1yeardaily` `TXT` resource record in the zone
+file for `verified.podcast`.
+
+## Subdomain Lifecycle
+
+Note that `1yeardaily.verified.podcast` has a different public key
+hash (address) than `verified.podcast`. A BNS node will only process a
+subsequent subdomain operation on `1yeardaily.verified.podcast` if it includes a
+signature from this address's private key. `verified.podcast` cannot generate
+updates; only the owner of `1yeardaily.verified.podcast can do so`.
+
+The lifecycle of a subdomain and its operations is shown in Figure 2.
+
+```
+ subdomain subdomain subdomain
+ creation update transfer
++----------------+ +----------------+ +----------------+
+| cicero | | cicero | | cicero |
+| owner="1Et..." | signed | owner="1Et..." | signed | owner="1cJ..." |
+| zf0="7e4..." |<--------| zf0="111..." |<--------| zf0="111..." |<---- ...
+| seqn=0 | | seqn=1 | | seqn=2 |
+| | | sig="xxxx" | | sig="xxxx" |
++----------------+ +----------------+ +----------------+
+ | | |
+ | off-chain | |
+~ ~ ~ ~ | ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~|~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ | ~ ~ ~ ~ ~ ~ ~ ...
+ | on-chain | |
+ V V (zone file hash ) V
++----------------+ +----------------+ +----------------+
+| res_publica.id | | jude.id | | res_publica.id |
+| NAME_UPDATE |<--------| NAME_UPDATE |<--------| NAME_UPDATE |<---- ...
++----------------+ +----------------+ +----------------+
+ blockchain blockchain blockchain
+ block block block
+
+
+Figure 2: Subdomain lifetime with respect to on-chain name operations. A new
+subdomain operation will only be accepted if it has a later "sequence=" number,
+and a valid signature in "sig=" over the transaction body. The "sig=" field
+includes both the public key and signature, and the public key must hash to
+the previous subdomain operation's "addr=" field.
+
+Thesubdomain-creation and subdomain-transfer transactions for
+"cicero.res_publica.id" are broadcast by the owner of "res_publica.id".
+However, any on-chain name ("jude.id" in this case) can broadcast a subdomain
+update for "cicero.res_publica.id".
+```
+
+Subdomain operations are ordered by sequence number, starting at 0. Each new
+subdomain operation must include:
+
+* The next sequence number
+* The public key that hashes to the previous subdomain transaction's address
+* A signature from the corresponding private key over the entire subdomain
+ operation.
+
+If two correctly-signed but conflicting subdomain operations are discovered
+(i.e. they have the same sequence number), the one that occurs earlier in the
+blockchain's history is accepted. Invalid subdomain operations are ignored.
+
+Combined, this ensures that a BNS node with all of the zone files with a given
+subdomain's operations will be able to determine the valid sequence of
+state-transitions it has undergone, and determine the current zone file and public
+key hash for the subdomain.
+
+## Resolving Subdomains
+
+Developers interact with subdomains the same way they interact with names.
+Using the BNS API, a developer can:
+
+### Look up a subdomain's public key and zone file ([reference](https://core.blockstack.org/#name-querying-get-name-info))
+
+```bash
+$ curl https://core.blockstack.org/v1/names/aaron.personal.id
+{
+ "address": "1PwztPFd1s2STMv4Ntq6UPBdYgHSBr5pdF",
+ "blockchain": "bitcoin",
+ "last_txid": "85e8273b0a38d3e9f0af7b4b72faf0907de9f4616afc101caac13e7bbc832394",
+ "status": "registered_subdomain",
+ "zonefile_hash": "a6dda6b74ffecf85f4a162627d8df59577243813",
+ "zonefile_txt": "$ORIGIN aaron.personal.id\n$TTL 3600\n_https._tcp URI 10 1 \"https://gaia.blockstack.org/hub/1PwztPFd1s2STMv4Ntq6UPBdYgHSBr5pdF/profile.json\"\n"
+}
+```
+
+### Look up a subdomain's transaction history ([reference](https://core.blockstack.org/#name-querying-name-history))
+
+```bash
+$ curl https://core.blockstack.org/v1/names/aaron.personal.id/history
+{
+ "509981": [
+ {
+ "address": "1PwztPFd1s2STMv4Ntq6UPBdYgHSBr5pdF",
+ "block_number": 509981,
+ "domain": "personal.id",
+ "name": "aaron.personal.id",
+ "sequence": 0,
+ "txid": "85e8273b0a38d3e9f0af7b4b72faf0907de9f4616afc101caac13e7bbc832394",
+ "value_hash": "a6dda6b74ffecf85f4a162627d8df59577243813",
+ "zonefile": "JE9SSUdJTiBhYXJvbi5wZXJzb25hbC5pZAokVFRMIDM2MDAKX2h0dHBzLl90Y3AgVVJJIDEwIDEgImh0dHBzOi8vZ2FpYS5ibG9ja3N0YWNrLm9yZy9odWIvMVB3enRQRmQxczJTVE12NE50cTZVUEJkWWdIU0JyNXBkRi9wcm9maWxlLmpzb24iCg=="
+ }
+ ]
+}
+```
+
+### Look up the list of names and subdomains owned by a given public key hash ([reference](https://core.blockstack.org/#name-querying-get-names-owned-by-address))
+
+```bash
+$ curl https://core.blockstack.org/v1/addresses/bitcoin/1PwztPFd1s2STMv4Ntq6UPBdYgHSBr5pdF
+{
+ "names": [
+ "aaron.personal.id"
+ ]
+}
+```
+
+## Subdomain Creation and Management
+
+Unlike an on-chain name, a subdomain owner needs an on-chain name owner's help
+to broadcast their subdomain operations. In particular:
+* A subdomain-creation transaction can only be processed by the owner of the on-chain
+name that shares its suffix. For example, only the owner of `res_publica.id`
+can broadcast subdomain-creation transactions for subdomain names ending in
+`.res_publica.id`.
+* A subdomain-transfer transaction can only be broadcast by the owner of the
+on-chain name that created it. For example, the owner of
+`cicero.res_publica.id` needs the owner of `res_publica.id` to broadcast a
+subdomain-transfer transaction to change `cicero.res_publica.id`'s public key.
+* In order to send a subdomain-creation or subdomain-transfer, all
+ of an on-chain name owner's zone files must be present in the Atlas network.
+ This lets the BNS node prove the *absence* of any conflicting subdomain-creation and
+subdomain-transfer operations when processing new zone files.
+* A subdomain update transaction can be broadcast by *any* on-chain name owner,
+ but the subdomain owner needs to find one who will cooperate. For example,
+the owner of `verified.podcast` can broadcast a subdomain-update transaction
+created by the owner of `cicero.res_publica.id`.
+
+That said, to create a subdomain, the subdomain owner generates a
+subdomain-creation operation for their desired name
+and gives it to the on-chain name owner.
+The on-chain name owner then uses Atlas to
+broadcast it to all other BNS nodes.
+
+Once created, a subdomain owner can use any on-chain name owner to broadcast a
+subdomain-update operation. To do so, they generate and sign the requisite
+subdomain operation and give it to an on-chain name owner, who then packages it
+with other subdomain operations into a DNS zone file
+and sends them all out on the Atlas network.
+
+If the subdomain owner wants to change the address of their subdomain, they need
+to sign a subdomain-transfer operation and give it to the on-chain name owner
+who created the subdomain. They then package it into a zone file and broadcast
+it.
+
+## Subdomain Registrars
+
+Because subdomain names are cheap, developers may be inclined to run
+subdomain registrars on behalf of their applications. For example,
+the name `personal.id` is used to register Blockstack application users without
+requiring them to spend any Bitcoin.
+
+We supply a reference
+implementation of a [BNS Subdomain Registrar](https://github.com/blockstack/subdomain-registrar)
+to help developers broadcast subdomain operations. Users would still own their
+subdomain names; the registrar simply gives developers a convenient way for them
+to register and manage them in the context of a particular application.
+Please see the [tutorial on running a subdomain registrar]({{ site.baseurl }}/core/naming/tutorial_subdomains.html) for
+details on how to use it.
diff --git a/_core/.svn/pristine/67/6719407d8bdca01639169e78cf9457bb40d85c52.svn-base b/_core/.svn/pristine/67/6719407d8bdca01639169e78cf9457bb40d85c52.svn-base
new file mode 100644
index 00000000..03ca186e
Binary files /dev/null and b/_core/.svn/pristine/67/6719407d8bdca01639169e78cf9457bb40d85c52.svn-base differ
diff --git a/_core/.svn/pristine/6b/6bf9e1c02b46d0d531e245e6d6ec0686551a225c.svn-base b/_core/.svn/pristine/6b/6bf9e1c02b46d0d531e245e6d6ec0686551a225c.svn-base
new file mode 100644
index 00000000..50b00abb
--- /dev/null
+++ b/_core/.svn/pristine/6b/6bf9e1c02b46d0d531e245e6d6ec0686551a225c.svn-base
@@ -0,0 +1,33 @@
+# Blockstack Resolver
+
+During 2014-2016, Bockstack resolver was a separate service (like DNS resolvers).
+It was merged into the Blockstack API in early 2017.
+
+The following (legacy) API call is still being supported by the Blockstack API:
+
+```
+http://localhost:5000/v2/users/fredwilson
+```
+
+And you can see a legacy resolver in action at http://resolver.onename.com/v2/users/fredwilson
+
+## Cron Job for Namespaces
+
+**Note: the instructions below need updating.**
+
+Currently, the resolver indexes all valid names in a local file which can be
+populated by running
+> $ ./refresh_names.sh
+
+On a production deployment, you should add a crond job to periodically run this
+script. You can edit your crontab file by:
+> $ crontab -e
+
+Here is a sample crontab file that runs the refresh script every two hours:
+```
+SHELL=/bin/bash
+HOME=/home/ubuntu
+
+#This is a comment
+0 */2 * * * /home/ubuntu/resolver/resolver/refresh_names.sh
+```
diff --git a/_core/.svn/pristine/76/762e235e2caf6c3d8e790985bcb01e2b4b17771d.svn-base b/_core/.svn/pristine/76/762e235e2caf6c3d8e790985bcb01e2b4b17771d.svn-base
new file mode 100644
index 00000000..7f624887
--- /dev/null
+++ b/_core/.svn/pristine/76/762e235e2caf6c3d8e790985bcb01e2b4b17771d.svn-base
@@ -0,0 +1,254 @@
+---
+layout: core
+permalink: /:collection/:path.html
+---
+## Resolve a name
+{:.no_toc}
+
+This section explains resolving BNS names and provides instructions for methods
+you can use to accomplish namespace resolution.
+
+* TOC
+{:toc}
+
+## Understand resolution
+
+BNS names are bound to both public keys and to about 40Kb of off-chain state.
+The off-chain state is encoded as a [DNS zone file](https://en.wikipedia.org/wiki/Zone_file),
+which contains routing information for discovering the user's Blockstack data
+(such as their profile and app data, which are hosted in the [Gaia storage
+system](https://github.com/blockstack/gaia)).
+
+The blockchain is not used to store this information directly. Instead, the
+blockchain stores the *public key hash* and the *zone file hash*. When
+indexing the blockchain, each BNS node builds a database with
+three columns: all the on-chain BNS names that have been registered, each
+name's public key hash, and each name's zone file's hash.
+In addition, each BNS node maintains the *transaction history* of each name.
+A developer can resolve a name to any configuration it was in at any prior
+point in time.
+
+Below is an example name table pulled from a live BNS node:
+
+| Name | Public key hash | Zone File Hash |
+|------|-----------------|--------------|
+| `ryan.id` | `15BcxePn59Y6mYD2fRLCLCaaHScefqW2No` | `a455954b3e38685e487efa41480beeb315f4ec65` |
+| `muneeb.id` | `1J3PUxY5uDShUnHRrMyU6yKtoHEUPhKULs` | `37aecf837c6ae9bdc9dbd98a268f263dacd00361` |
+| `jude.id` | `16EMaNw3pkn3v6f2BgnSSs53zAKH4Q8YJg` | `b6e99200125e70d634b17fe61ce55b09881bfafd` |
+| `verified.podcast` | `1MwPD6dH4fE3gQ9mCov81L1DEQWT7E85qH` | `6701ce856620d4f2f57cd23b166089759ef6eabd` |
+| `cicero.res_publica.id` | `1EtE77Aa5AA8etzF2irk56vvkS4v7rZ7PE` | `7e4ac75f9d79ba9d5d284fac19617497433b832d` |
+| `podsaveamerica.verified.podcast` | `1MwPD6dH4fE3gQ9mCov81L1DEQWT7E85qH` | `0d6f090db8945aa0e60759f9c866b17645893a95` |
+
+In practice, the zone file hash is the `RIPEMD160` hash of the `SHA256` hash of
+the zone file, and the public key is the `base58check`-encoded `RIPEMD160` hash
+of the double-`SHA256` hash of the ECDSA public key (i.e. a Bitcoin address).
+
+The BNS consensus rules ensure that
+a BNS name can only be registered if it is not already taken, and that only the
+user who owns the name's private key can change its public key hash or zone file
+hash. This means that a name's public key and zone file can be stored anywhere,
+since they can be authenticated using the hashes discovered by indexing the
+blockchain under the BNS consensus rules.
+
+BNS nodes implement a decentralized storage system for zone files called the
+[Atlas network]({{ site.baseurl }}/core/atlas/overview.html). In this system, BNS nodes eagerly replicate
+all the zone files they know about to one another, so that eventually every BNS
+node has a full replica of all zone files.
+
+The public keys for names are stored off-chain in [Gaia](https://github.com/blockstack/gaia).
+The user controls where their public keys are hosted using the zone file
+contents (if they are hosted online anywhere at all).
+
+Developers can query this table via the BNS API. The API offers routes
+to do the following:
+
+## Look up a name's public key and zone file ([reference](https://core.blockstack.org/#name-querying-get-name-info))
+
+```bash
+$ curl https://core.blockstack.org/v1/names/muneeb.id
+{
+ "address": "1J3PUxY5uDShUnHRrMyU6yKtoHEUPhKULs",
+ "blockchain": "bitcoin",
+ "expire_block": 599266,
+ "last_txid": "7e16e8688ca0413a398bbaf16ad4b10d3c9439555fc140f58e5ab4e50793c476",
+ "status": "registered",
+ "zonefile": "$ORIGIN muneeb.id\n$TTL 3600\n_http._tcp URI 10 1 \"https://gaia.blockstack.org/hub/1J3PUxY5uDShUnHRrMyU6yKtoHEUPhKULs/0/profile.json\"\n",
+ "zonefile_hash": "37aecf837c6ae9bdc9dbd98a268f263dacd00361"
+}
+```
+
+Note that the `zonefile` field is given with the off-chain data that hashes
+to the `zonefile_hash` field.
+
+## List all names the node knows about ([reference](https://core.blockstack.org/#name-querying-get-all-names))
+
+```bash
+$ curl https://core.blockstack.org/v1/names?page=0
+[
+ "judecn.id",
+ "3.id",
+ "4.id",
+ "8.id",
+ "e.id",
+ "h.id",
+ "5.id",
+ "9.id",
+ "i.id",
+ "l.id",
+ "p.id",
+ "w.id",
+ "ba.id",
+ "df.id",
+...
+]
+```
+
+Each page returns 100 names. While no specific ordering is mandated by the
+protocol, the reference implementation orders names by their order of creation
+in the blockchain.
+
+## Look up the history of states a name was in ([reference](https://core.blockstack.org/#name-querying-name-history))
+
+```bash
+$ curl https://core.blockstack.org/v1/names/patrickstanley.id/history
+{
+ "445838": [
+ {
+ "address": "1occgbip7tFDXX9MvzQhcnTUUjcVX2dYK",
+ "block_number": 445838,
+ "burn_address": "1111111111111111111114oLvT2",
+ "consensus_hash": "7b696b6f4060b792d41912068944d73b",
+ "op": "?",
+ "op_fee": 25000,
+ "opcode": "NAME_PREORDER",
+ "preorder_hash": "26bf7874706ac761afdd403ed6b3b9578fb01a34",
+ "sender": "76a91408d0dd44c1f0a3a4f0957ae95901929d7d66d55788ac",
+ "sender_pubkey": "039a8948d339ecbff44cf426cb85d90fce876f1658d385cdc47f007f279be626ea",
+ "txid": "6730ae09574d5935ffabe3dd63a9341ea54fafae62fde36c27738e9ee9c4e889",
+ "vtxindex": 40
+ }
+ ],
+ "445851": [
+ {
+ "address": "17CbHgTgBG3kLedXNneEKBkCTgW2fyrnUD",
+ "block_number": 445838,
+ "consensus_hash": null,
+ "first_registered": 445851,
+ "importer": null,
+ "importer_address": null,
+ "last_creation_op": "?",
+ "last_renewed": 445851,
+ "name": "patrickstanley.id",
+ "name_hash128": "683a3e1ee5f0296833c56e481cf41b77",
+ "namespace_block_number": 373601,
+ "namespace_id": "id",
+ "op": ":",
+ "op_fee": 25000,
+ "opcode": "NAME_REGISTRATION",
+ "preorder_block_number": 445838,
+ "preorder_hash": "26bf7874706ac761afdd403ed6b3b9578fb01a34",
+ "revoked": false,
+ "sender": "76a9144401f3be5311585ea519c1cb471a8dc7b02fd6ee88ac",
+ "sender_pubkey": "039a8948d339ecbff44cf426cb85d90fce876f1658d385cdc47f007f279be626ea",
+ "transfer_send_block_id": null,
+ "txid": "55b8b42fc3e3d23cbc0f07d38edae6a451dfc512b770fd7903725f9e465b2925",
+ "value_hash": null,
+ "vtxindex": 54
+ }
+ ],
+ "445873": [
+ {
+ "address": "17CbHgTgBG3kLedXNneEKBkCTgW2fyrnUD",
+ "block_number": 445838,
+ "consensus_hash": "18b8d69f0182b89ccb1aa536f83be18a",
+ "first_registered": 445851,
+ "importer": null,
+ "importer_address": null,
+ "last_creation_op": "?",
+ "last_renewed": 445851,
+ "name": "patrickstanley.id",
+ "name_hash128": "683a3e1ee5f0296833c56e481cf41b77",
+ "namespace_block_number": 373601,
+ "namespace_id": "id",
+ "op": "+",
+ "op_fee": 25000,
+ "opcode": "NAME_UPDATE",
+ "preorder_block_number": 445838,
+ "preorder_hash": "26bf7874706ac761afdd403ed6b3b9578fb01a34",
+ "revoked": false,
+ "sender": "76a9144401f3be5311585ea519c1cb471a8dc7b02fd6ee88ac",
+ "sender_pubkey": "039a8948d339ecbff44cf426cb85d90fce876f1658d385cdc47f007f279be626ea",
+ "transfer_send_block_id": null,
+ "txid": "dc478659fc684a1a6e1e09901971e82de11f4dfe2b32a656700bf9a3b6030719",
+ "value_hash": "02af0ef21161ad06b0923106f40b994b9e4c1614",
+ "vtxindex": 95
+ }
+ ],
+ "445884": [
+ {
+ "address": "1GZqrVbamkaE6YNveJFWK6cDrCy6bXyS6b",
+ "block_number": 445838,
+ "consensus_hash": "18b8d69f0182b89ccb1aa536f83be18a",
+ "first_registered": 445851,
+ "importer": null,
+ "importer_address": null,
+ "last_creation_op": "?",
+ "last_renewed": 445851,
+ "name": "patrickstanley.id",
+ "name_hash128": "683a3e1ee5f0296833c56e481cf41b77",
+ "namespace_block_number": 373601,
+ "namespace_id": "id",
+ "op": ">>",
+ "op_fee": 25000,
+ "opcode": "NAME_TRANSFER",
+ "preorder_block_number": 445838,
+ "preorder_hash": "26bf7874706ac761afdd403ed6b3b9578fb01a34",
+ "revoked": false,
+ "sender": "76a914aabffa6dd90d731d3a349f009323bb312483c15088ac",
+ "sender_pubkey": null,
+ "transfer_send_block_id": 445875,
+ "txid": "7a0a3bb7d39b89c3638abc369c85b5c028d0a55d7804ba1953ff19b0125f3c24",
+ "value_hash": "02af0ef21161ad06b0923106f40b994b9e4c1614",
+ "vtxindex": 16
+ }
+ ]
+}
+```
+
+All of the above information is extracted from the blockchain. Each top-level
+field encodes the states the name transitioned to at the given block height (e.g.
+445838, 445851, 445873, adn 445884). At each block height, the name's zone file
+hashes are returned in the order they were discovered in the blockchain.
+
+Each name state contains a lot of ancillary data that is used internally by
+other API calls and client libraries. The relevant fields for this document's
+scope are:
+
+* `address`: This is the base58check-encoded public key hash.
+* `name`: This is the name queried.
+* `value_hash`: This is the zone file hash.
+* `opcode`: This is the type of transaction that was processed.
+* `txid`: This is the transaction ID in the underlying blockchain.
+
+The name's *entire* history is returned. This includes the history of the name
+under its previous owner, if the name expired and was reregistered.
+
+## Look up the list of names owned by a given public key hash ([reference](https://core.blockstack.org/#name-querying-get-names-owned-by-address))
+
+```bash
+$ curl https://core.blockstack.org/v1/addresses/bitcoin/16EMaNw3pkn3v6f2BgnSSs53zAKH4Q8YJg
+{
+ "names": [
+ "judecn.id",
+ "patrickstanley1.id",
+ "abcdefgh123456.id",
+ "duckduckgo_tor.id",
+ "jude.id",
+ "blockstacknewyear2017.id",
+ "jude.statism.id"
+ ]
+}
+```
+
+Note that this API endpoint includes names and
+[subdomains](#bns-subdomains).
diff --git a/_core/.svn/pristine/77/772bb1e0b5c7f9fcb8d8e9906d819f8c1bc6ac4b.svn-base b/_core/.svn/pristine/77/772bb1e0b5c7f9fcb8d8e9906d819f8c1bc6ac4b.svn-base
new file mode 100644
index 00000000..3d01fe23
--- /dev/null
+++ b/_core/.svn/pristine/77/772bb1e0b5c7f9fcb8d8e9906d819f8c1bc6ac4b.svn-base
@@ -0,0 +1,78 @@
+---
+layout: core
+permalink: /:collection/:path.html
+---
+# Understand Namespaces
+
+Namespaces are the top-level naming objects in BNS.
+
+They control a few properties about the names within them:
+* How expensive they are to register
+* How long they last before they have to be renewed
+* Who (if anyone) receives the name registration fees
+* Who is allowed to seed the namespace with its initial names.
+
+At the time of this writing, by far the largest BNS namespace is the `.id`
+namespace. Names in the `.id` namespace are meant for resolving user
+identities. Short names in `.id` are more expensive than long names, and have
+to be renewed by their owners every two years. Name registration fees are not
+paid to anyone in particular---they are instead sent to a "black hole" where
+they are rendered unspendable (the intention is to discourage ID sqautters).
+
+Unlike DNS, *anyone* can create a namespace and set its properties. Namespaces
+are created on a first-come first-serve basis, and once created, they last
+forever.
+
+However, creating a namespace is not free. The namespace creator must *burn*
+cryptocurrency to do so. The shorter the namespace, the more cryptocurrency
+must be burned (i.e. short namespaces are more valuable than long namespaces).
+For example, it cost Blockstack PBC 40 BTC to create the `.id` namespace in 2015
+(in transaction
+`5f00b8e609821edd6f3369ee4ee86e03ea34b890e242236cdb66ef6c9c6a1b281`).
+
+Namespaces can be between 1 and 19 characters long, and are composed of the
+characters `a-z`, `0-9`, `-`, and `_`.
+
+## Namespace Organization
+
+BNS names are organized into a global name hierarchy. There are three different
+layers in this hierarchy related to naming:
+
+* **Namespaces**. These are the top-level names in the hierarchy. An analogy
+ to BNS namespaces are DNS top-level domains. Existing BNS namespaces include
+`.id`, `.podcast`, and `.helloworld`. All other names belong to exactly one
+namespace. Anyone can create a namespace, but in order for the namespace
+to be persisted, it must be *launched* so that anyone can register names in it.
+Namespaces are not owned by their creators.
+
+* **BNS names**. These are names whose records are stored directly on the
+ blockchain. The ownership and state of these names are controlled by sending
+blockchain transactions. Example names include `verified.podcast` and
+`muneeb.id`. Anyone can create a BNS name, as long as the namespace that
+contains it exists already. The state for BNS names is usually stored in the [Atlas
+network]({{ site.baseurl }}/core/atlas/overview.html).
+
+* **BNS subdomains**. These are names whose records are stored off-chain,
+but are collectively anchored to the blockchain. The ownership and state for
+these names lives within the [Atlas network]({{ site.baseurl }}/core/atlas/overview.html). While BNS
+subdomains are owned by separate private keys, a BNS name owner must
+broadcast their subdomain state. Example subdomains include `jude.personal.id`
+and `podsaveamerica.verified.podcast`. Unlike BNS namespaces and names, the
+state of BNS subdomains is *not* part of the blockchain consensus rules.
+
+A feature comparison matrix summarizing the similarities and differences
+between these name objects is presented below:
+
+| Feature | **Namespaces** | **BNS names** | **BNS Subdomains** |
+|---------|----------------|---------------|--------------------|
+| Globally unique | X | X | X |
+| Human-meaningful | X | X | X |
+| Owned by a private key | | X | X |
+| Anyone can create | X | X | [1] |
+| Owner can update | | X | [1] |
+| State hosted on-chain | X | X | |
+| State hosted off-chain | | X | X |
+| Behavior controlled by consensus rules | X | X | |
+| May have an expiration date | | X | |
+
+[1] Requires the cooperation of a BNS name owner to broadcast its transactions
diff --git a/_core/.svn/pristine/7a/7aafbd433698ae8f0d8b123f66c97288e7b37f2a.svn-base b/_core/.svn/pristine/7a/7aafbd433698ae8f0d8b123f66c97288e7b37f2a.svn-base
new file mode 100644
index 00000000..a16c5d2a
--- /dev/null
+++ b/_core/.svn/pristine/7a/7aafbd433698ae8f0d8b123f66c97288e7b37f2a.svn-base
@@ -0,0 +1,1806 @@
+# Group Core Node Administration
+
+Blockstack Core's API module provides a set of API calls for interacting with
+the node's configuration. Most configuration state is in the [Blockstack
+Browser](https://github.com/blockstack/blockstack-browser). Client-side state
+is managed by [blockstack.js](https://github.com/blockstack/blockstack.js).
+
+## Ping the node [GET /v1/node/ping]
+
+Ping the Blockstack node to see if it's alive.
+
++ Public Endpoint
++ Response 200 (application/json)
+ + Body
+
+ {
+ "status": "alive",
+ "version": "###version###"
+ }
+ + Schema
+
+ {
+ "type": "object",
+ "properties": {
+ "status": {
+ "type": "string"
+ },
+ "version": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "status",
+ "version"
+ ]
+ }
+
+# Group Managing Names
+
+## Fetch zone file [GET /v1/names/{name}/zonefile]
+
+Fetch a user's raw zone file. This only works for RFC-compliant zone files.
+This method returns an error for names that have non-standard zone files.
+
++ Public Endpoint
++ Parameters
+ + name: bar.test (string) - fully-qualified name
++ Response 200 (application/json)
+ + Body
+
+ {
+ "zonefile": "$ORIGIN bar.test\n$TTL 3600\n_https._tcp URI 10 1 \"https://gaia.blockstack.org/hub/17Zijx61Sp7SbVfRTdETo7PhizJHYEUxbY/profile.json\"\n"
+ }
+
+ + Schema
+
+ {
+ 'anyOf': [
+ {
+ 'type': 'object',
+ 'properties': {
+ 'zonefile': {
+ 'type': 'string',
+ 'pattern': '.+',
+ },
+ },
+ {
+ 'type': 'object',
+ 'properties': {
+ 'error': {
+ 'type': 'string',
+ 'pattern': '.+',
+ },
+ },
+ ]
+ }
+
++ Response 400 (application/json)
+ + Body
+
+ { "error": "Invalid name or subdomain" }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'error': { 'type': 'string' },
+ },
+ }
+
++ Response 404 (application/json)
+ + Body
+
+ { "error": "No zone file for name" }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'error': { 'type': 'string' },
+ },
+ }
+
+# Group Name Querying
+
+This family of API endpoints deals with querying name information.
+
+## Get all names [GET /v1/names?page={page}]
+Fetch a list of all names known to the node.
++ Public Endpoint
++ Parameters
+ + page: 23 (number) - names are returned in pages of size 100,
+ so specify the page number.
++ Response 200 (application/json)
+ + Body
+
+ [ "aldenquimby.id", "aldeoryn.id",
+ "alderete.id", "aldert.id",
+ "aldi.id", "aldighieri.id", ... ]
+
+ + Schema
+
+ {
+ 'type': 'array',
+ 'items': {
+ 'type': 'string',
+ 'pattern': '^([a-z0-9\\-_.+]{3,37})$',
+ }
+ }
+
++ Response 400 (application/json)
+ + Body
+
+ { "error": "Invalid page" }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'error': { 'type': 'string' },
+ },
+ }
+
+
+## Get all subdomains [GET /v1/subdomains?page={page}]
+Fetch a list of all names known to the node.
++ Public Endpoint
++ Parameters
+ + page: 3 (number) - names are returned in pages of size 100,
+ so specify the page number.
++ Response 200 (application/json)
+ + Body
+
+ [ ...
+ "collegeinfogeek.verified.podcast",
+ "collider.verified.podcast",
+ "combatandclassics.verified.podcast",
+ "combatjack.verified.podcast",
+ "comedybangbang.verified.podcast",
+ "comedybutton.verified.podcast",
+ "commonsense.verified.podcast",
+ "concilio002.personal.id", ... ]
+
+ + Schema
+
+ {
+ 'type': 'array',
+ 'items': {
+ 'type': 'string',
+ 'pattern': '^([a-z0-9\\-_.+]{3,37})\.([a-z0-9\\-_.+]{3,37})$',
+ }
+ }
+
++ Response 400 (application/json)
+ + Body
+
+ { "error": "Invalid page" }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'error': { 'type': 'string' },
+ },
+ }
+
+## Get name info [GET /v1/names/{name}]
++ Public Endpoint
++ Subdomain Aware
++ Parameters
+ + name: muneeb.id (string) - fully-qualified name
++ Response 200 (application/json)
+ + Body
+
+ {
+ "address": "1J3PUxY5uDShUnHRrMyU6yKtoHEUPhKULs",
+ "blockchain": "bitcoin",
+ "expire_block": 599266,
+ "grace_period": false,
+ "last_txid": "1edfa419f7b83f33e00830bc9409210da6c6d1db60f99eda10c835aa339cad6b",
+ "renewal_deadline": 604266,
+ "resolver": null,
+ "status": "registered",
+ "zonefile": "$ORIGIN muneeb.id\n$TTL 3600\n_http._tcp IN URI 10 1 \"https://gaia.blockstack.org/hub/1J3PUxY5uDShUnHRrMyU6yKtoHEUPhKULs/0/profile.json\"\n",
+ "zonefile_hash": "37aecf837c6ae9bdc9dbd98a268f263dacd00361"
+ }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'address': {
+ 'type': 'string',
+ 'pattern': "^([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]+)$",
+ },
+ 'blockchain': {
+ 'type': 'string',
+ 'pattern': '^bitcoin$',
+ },
+ 'expire_block': {
+ 'type': 'integer',
+ 'minimum': 0,
+ },
+ 'grace_period': {
+ 'type': 'integer',
+ 'minimum': 0,
+ },
+ 'last_txid': {
+ 'type': 'string',
+ 'pattern': '^[0-9a-fA-F]+$',
+ },
+ 'resolver': {
+ 'type': 'string',
+ },
+ 'status': {
+ 'type': 'string',
+ 'pattern': '^(registered|revoked)$',
+ },
+ 'zonefile': {
+ 'anyOf': [
+ {
+ 'type': 'string',
+ },
+ {
+ 'type': 'object',
+ 'properties': {
+ 'error': {
+ 'type': 'string',
+ },
+ },
+ },
+ ],
+ },
+ 'zonefile_hash': {
+ 'type': 'string',
+ 'pattern': '^[0-9a-fA-F]{20}$`,
+ },
+ },
+ { 'required':
+ [
+ 'address', 'blockchain', 'last_txid',
+ 'status', 'zonefile', 'zonefile_hash'
+ ]
+ }
+ }
+
++ Response 400 (application/json)
+ + Body
+
+ { "error": "Invalid name or subdomain" }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'error': { 'type': 'string' },
+ },
+ }
+
++ Response 404 (application/json)
+ + Body
+
+ { "error": "No such name" }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'error': { 'type': 'string' },
+ },
+ }
+
+## Get name history [GET /v1/names/{name}/history?page={page}]
+Get a history of all blockchain records of a registered name.
++ Public Endpoint
++ Subdomain aware
++ Parameters
+ + name: muneeb.id (string) - name to query
+ + page: 0 (integer) - the page (in 20-entry pages) of the history to fetch
++ Response 200 (application/json)
+ + Body
+
+ {
+ "373821": [
+ {
+ "address": "1QJQxDas5JhdiXhEbNS14iNjr8auFT96GP",
+ "block_number": 373821,
+ "consensus_hash": null,
+ "first_registered": 373821,
+ "importer": "76a9143e2b5fdd12db7580fb4d3434b31d4fe9124bd9f088ac",
+ "importer_address": "16firc3qZU97D1pWkyL6ZYwPX5UVnWc82V",
+ "last_creation_op": ";",
+ "last_renewed": 373821,
+ "name": "muneeb.id",
+ "name_hash128": "deb7fe99776122b77925cbf0a24ab6f8",
+ "namespace_block_number": 373601,
+ "namespace_id": "id",
+ "op": ";",
+ "op_fee": 100000.0,
+ "opcode": "NAME_IMPORT",
+ "preorder_block_number": 373821,
+ }
+ ]
+ }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'patternProperties': {
+ '^[0-9]+': {
+ 'type': 'array',
+ 'items': {
+ 'type': 'object',
+ 'properties': {
+ 'address': {
+ 'type': 'string',
+ 'pattern': "^([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]+)$",
+ },
+ 'base': {
+ 'type': 'integer',
+ 'minimum': 0,
+ 'maximum': 255,
+ },
+ 'buckets': {
+ 'anyOf': [
+ {
+ 'type': 'array',
+ 'items': {
+ 'type': 'integer',
+ 'minItems': 16,
+ 'maxItems': 16,
+ },
+ },
+ {
+ 'type': 'null',
+ },
+ ],
+ },
+ 'block_number': {
+ 'type': 'integer',
+ 'minimum': 0,
+ },
+ 'coeff': {
+ 'anyOf': [
+ {
+ 'type': 'integer',
+ 'minimum': 0,
+ 'maximum': 255,
+ },
+ {
+ 'type': 'null'
+ },
+ ],
+ },
+ 'consensus_hash': {
+ 'anyOf': [
+ {
+ 'type': 'string',
+ 'pattern': '^[0-9a-fA-F]{32}',
+ },
+ {
+ 'type': 'null'
+ },
+ ],
+ },
+ 'domain': {
+ 'type': 'string',
+ 'pattern': '^([a-z0-9\\-_.+]{3,37})$',
+ },
+ 'fee': {
+ 'type': 'integer',
+ 'minimum': 0,
+ },
+ 'first_registered': {
+ 'type': 'integer',
+ 'minimum': 0,
+ },
+ 'history_snapshot': {
+ 'type': 'boolean',
+ },
+ 'importer': {
+ 'anyOf': [
+ {
+ 'type': 'string',
+ 'pattern': '^76[aA]914[0-9a-fA-F]{40}88[aA][cC]$',
+ },
+ {
+ 'type': 'null',
+ },
+ ],
+ },
+ 'importer_address': {
+ 'anyOf': [
+ {
+ 'type': 'string',
+ 'pattern': "^([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]+)$",
+ },
+ {
+ 'type': 'null',
+ },
+ ],
+ },
+ 'last_renewed': {
+ 'type': 'integer',
+ 'minimum': 0,
+ },
+ 'name': {
+ 'type': 'string',
+ 'pattern': '^([a-z0-9\\-_.+]{3,37})\.([a-z0-9\\-_.+]{3,37})$',
+ },
+ 'op': {
+ 'type': 'string',
+ 'pattern': '^([>?+~:!&*:;#]{1}|>>|>~|::)$',
+ },
+ 'op_fee': {
+ 'type': 'number',
+ },
+ 'opcode': {
+ 'type': 'string',
+ 'pattern': '^NAME_TRANSFER|NAME_PREORDER|NAME_UPDATE|NAME_REVOKE|NAME_REGISTRATION|NAMESPACE_READY|NAMESPACE_REVEAL|NAMESPACE_PREORDER|NAME_RENEWAL|NAME_IMPORT|ANNOUNCE$'
+ },
+ 'revoked': {
+ 'type': 'boolean',
+ },
+ 'sender': {
+ 'type': 'string',
+ 'pattern': '^([0-9a-fA-F]+)$',
+ },
+ 'sender_pubkey': {
+ 'anyOf': [
+ {
+ 'type': 'string',
+ 'pattern': '^([0-9a-fA-F]+)$',
+ },
+ {
+ 'type': 'null'
+ },
+ ],
+ },
+ 'sequence': {
+ 'type': 'integer',
+ 'minimum': 0
+ }
+ 'recipient': {
+ 'anyOf': [
+ {
+ 'type': 'string',
+ 'pattern': '^([0-9a-fA-F]+)$',
+ },
+ {
+ 'type': 'null'
+ },
+ ],
+ },
+ 'recipient_address': {
+ 'anyOf': [
+ {
+ 'type': 'string',
+ 'pattern': '^([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]+)$',
+ },
+ {
+ 'type': 'null'
+ },
+ ],
+ },
+ 'recipient_pubkey': {
+ 'anyOf': [
+ {
+ 'type': 'string',
+ 'pattern': '^([0-9a-fA-F]+)$',
+ },
+ {
+ 'type': 'null'
+ },
+ ],
+ },
+ 'txid': {
+ 'type': 'string',
+ 'pattern': '^([0-9a-fA-F]+)$',
+ },
+ 'value_hash': {
+ 'anyOf': [
+ {
+ 'type': 'string',
+ 'pattern': '^([0-9a-fA-F]{40})$',
+ },
+ {
+ 'type': 'null',
+ },
+ ],
+ },
+ 'vtxindex': {
+ 'type': 'integer',
+ 'minimum': 0,
+ },
+ },
+ 'required': [
+ 'txid',
+ 'vtxindex'
+ ],
+ }
+ }
+ }
+ }
+
++ Response 400 (application/json)
+ + Body
+
+ { "error": "Invalid page" }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'error': { 'type': 'string' },
+ },
+ }
+
++ Response 404 (application/json)
+ + Body
+
+ { "error": "No such name" }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'error': { 'type': 'string' },
+ },
+ }
+
+## Get historical zone file [GET /v1/names/{name}/zonefile/{zoneFileHash}]
+Fetches the historical zonefile specified by the username and zone hash.
++ Public Endpoint
++ Subdomain aware
++ Parameters
+ + name: muneeb.id (string) username to fetch
+ + zoneFileHash: b100a68235244b012854a95f9114695679002af9
++ Response 200 (application/json)
+ + Body
+
+ {
+ "zonefile": "$ORIGIN muneeb.id\n$TTL 3600\n_http._tcp IN URI 10 1 \"https://blockstack.s3.amazonaws.com/muneeb.id\"\n"
+ }
+
+ + Schema
+
+ {
+ 'anyOf': [
+ {
+ 'type': 'object',
+ 'properties': {
+ 'zonefile': { 'type': 'string' },
+ },
+ },
+ {
+ 'type': 'object',
+ 'properties': {
+ 'error': { 'type': 'string' },
+ },
+ },
+ ],
+ }
+
++ Response 400 (application/json)
+ + Body
+
+ { "error": "Invalid name or subdomain" }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'error': { 'type': 'string' },
+ },
+ }
+
++ Response 404 (application/json)
+ + Body
+
+ { "error": "No such zonefile" }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'error': { 'type': 'string' },
+ },
+ }
+
+## Get names owned by address [GET /v1/addresses/{blockchain}/{address}]
+Retrieves a list of names owned by the address provided.
++ Subdomain Aware
++ Public Endpoint
++ Parameters
+ + blockchain: bitcoin (string) - the layer-1 blockchain for the address
+ + address: 1QJQxDas5JhdiXhEbNS14iNjr8auFT96GP (string) - the address to lookup
+
++ Response 200 (application/json)
+ + Body
+
+ {
+ "names": ["muneeb.id"]
+ }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'names': {
+ 'type': 'array',
+ 'items': {
+ 'type': 'string',
+ 'pattern': '^([a-z0-9\-_.+]{3,37})$',
+ }
+ }
+ }
+ }
+
++ Response 404 (application/json)
+ + Body
+
+ { "error": "Unsupported blockchain" }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'error': { 'type': 'string' },
+ },
+ }
+
+# Group Price Checks
+
+## Get namespace price [GET /v1/prices/namespaces/{tld}]
+
+This endpoint is used to get the price of a namespace.
+
++ Public Endpoint
++ Parameters
+ + tld: id (string) - namespace to query price for
++ Response 200 (application/json)
+ + Body
+
+ {
+ "satoshis": 4000000000,
+ "units": "BTC",
+ "amount": "4000000000"
+ }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'units': {
+ 'type': 'string',
+ },
+ 'amount': {
+ 'type': 'string',
+ 'pattern': '^[0-9]+$',
+ },
+ 'satoshis': {
+ 'type': 'integer',
+ 'minimum': 0,
+ },
+ },
+ 'required': [ 'satoshis' ]
+ }
+
++ Response 400 (application/json)
+ + Body
+
+ { "error": "Invalid namepace" }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'error': { 'type': 'string' },
+ },
+ }
+
+## Get name price [GET /v1/prices/names/{name}]
+
+This endpoint is used to get the price of a name. If you are using a public
+endpoint, you should *only* rely on the `name_price` field in the returned JSON
+blob.
+
+The other fields are relevant only for estimating the cost of registering a
+name. You register a name via
+[blockstack.js](https://github.com/blockstack/blockstack.js) or the [Blockstack
+Browser](https://github.com/blockstack/blockstack-browser)).
+
++ Public Endpoint
++ Parameters
+ + name: muneeb.id (string) - name to query price information for
++ Response 200 (application/json)
+ + Body
+
+ {
+ "name_price": {
+ "satoshis": 100000,
+ "units": "BTC",
+ "amount": "100000"
+ },
+ }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'name_price': {
+ 'type': 'object',
+ 'properties': {
+ 'satoshis': { 'type': 'integer', 'minimum': 0 },
+ 'units': { 'type': 'string' },
+ 'amount': { 'type': 'string', 'pattern': '^[0-9]+$' }
+ },
+ 'required': [ 'satoshis' ],
+ },
+ 'required': [ 'name_price' ]
+ }
+ }
+
++ Response 400 (application/json)
+ + Body
+
+ { "error": "Invalid name" }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'error': { 'type': 'string' },
+ },
+ }
+
+## Get namespace price [GET /v2/prices/namespaces/{tld}]
+
+This endpoint is used to get the price of a namespace, while explicitly
+indicating the cryptocurrency units. This is because going forward, namespaces
+are not necessarily priced in Bitcoin.
+
++ Public Endpoint
++ Parameters
+ + tld: id (string) - namespace to query price for
++ Response 200 (application/json)
+ + Body
+
+ {
+ "units": "BTC",
+ "amount": "4000000000"
+ }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'units': {
+ 'type': 'string',
+ },
+ 'amount': {
+ 'type': 'string',
+ 'pattern': '^[0-9]+$',
+ },
+ },
+ 'required': [ 'units', 'amount' ]
+ }
+
++ Response 400 (application/json)
+ + Body
+
+ { "error": "Invalid namespace" }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'error': { 'type': 'string' },
+ },
+ },
+
+## Get name price [GET /v2/prices/names/{name}]
+
+This endpoint is used to get the price of a name, denoted in a specific
+cryptocurrency (not necessarily Bitcoin).
+
++ Public Endpoint
++ Parameters
+ + name: muneeb.id (string) - name to query price information for
++ Response 200 (application/json)
+ + Body
+
+ {
+ "name_price": {
+ "units": "BTC",
+ "amount": "100000"
+ },
+ }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'name_price': {
+ 'type': 'object',
+ 'properties': {
+ 'units': { 'type': 'string' },
+ 'amount': { 'type': 'string', 'pattern': '^[0-9]+$' }
+ },
+ 'required': [ 'units', 'amount' ],
+ },
+ 'required': [ 'name_price' ]
+ }
+ }
+
++ Response 400 (application/json)
+ + Body
+
+ { "error": "Invalid name" }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'error': { 'type': 'string' },
+ },
+ },
+
+# Group Blockchain Operations
+
+## Get consensus hash [GET /v1/blockchains/{blockchainName}/consensus]
+
+Get the current Blockstack consensus hash on a blockchain.
++ Public Endpoint
++ Parameters
+ + blockchainName : bitcoin (string) - the given blockchain
++ Response 200 (application/json)
+ + Body
+
+ {
+ "consensus_hash": "2fcbdf66c350894fe03b42c6a2e8a6ac"
+ }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'consensus_hash': {
+ 'type': 'string',
+ 'pattern': '^[0-9a-fA-F]{32}$`,
+ },
+ },
+ }
+
++ Response 404 (application/json)
+ + Body
+
+ { "error": "Unsupported blockchain" }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'error': { 'type': 'string' },
+ },
+ }
+
+## Get total names on blockchain [GET /v1/blockchains/{blockchainName}/name_count{?all}]
+
+Get a count of the number of names on a blockchain. This does not include
+subdomains.
++ Public Endpoint
++ Parameters
+ + blockchainName: bitcoin (string) - the given blockchain
+ + all: true (enum[string], optional) - include expired names
++ Response 200 (application/json)
+ + Body
+
+ {
+ "names_count": 73950
+ }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'names_count': {
+ 'type': 'integer',
+ 'minimum': 0,
+ },
+ },
+ }
+
++ Response 404 (application/json)
+ + Body
+
+ { "error": "Unsupported blockchain" }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'error': { 'type': 'string' },
+ },
+ },
+
+
+## Get total subdomains on blockchain [GET /v1/blockchains/{blockchainName}/subdomains_count]
+Get the number of subdomains on a blockchain.
++ Public Endpoint
++ Parameters
+ + blockchainName: bitcoin (string) - the given blockchain
++ Response 200 (application/json)
+ + Body
+
+ {
+ "names_count": 1646
+ }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'names_count': {
+ 'type': 'integer',
+ 'minimum': 0,
+ },
+ },
+ }
+
++ Response 404 (application/json)
+ + Body
+
+ { "error": "Unsupported blockchain" }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'error': { 'type': 'string' },
+ },
+ },
+
+
+## Get operations in block [GET /v1/blockchains/{blockchainName}/operations/{blockHeight}]
+
+Get the Blockstack operations in a given block
++ Public Endpoint
++ Parameters
+ + blockchainName : bitcoin (string) - the given blockchain
+ + blockHeight : 462592 (integer) - the block height
++ Response 200 (application/json)
+ + Body
+
+ [
+ {
+ "address": "1GS1eHthSK2gqnU9MW9Nis1pUyHP3bJnFK",
+ "block_number": 462592,
+ "burn_address": "1111111111111111111114oLvT2",
+ "consensus_hash": "d206b2f615de00803402cade4d0d51d4",
+ "op": "?",
+ "op_fee": 6250,
+ "opcode": "NAME_PREORDER",
+ "preorder_hash": "ba22cdf24b05b9a7972e13ada69f96a7850b471e",
+ "sender": "76a914a944d29012f83c00105778e0bc717c46ea2accfc88ac",
+ "sender_pubkey": "0343b263f7adc6ae59e8d8310f4a6a87799f6b10cec608f3236cd6a802ffc71728",
+ "txid": "b3f4f7a43d60666d1a9b42131f9117ad7deac34a478b6ca152344da3d734691f",
+ "vtxindex": 173
+ },
+ {
+ "address": "1gijbF8NkbgwzcoZR1nXMa76NbdcD7GQW",
+ "block_number": 462592,
+ "burn_address": "1111111111111111111114oLvT2",
+ "consensus_hash": "d206b2f615de00803402cade4d0d51d4",
+ "op": "?",
+ "op_fee": 6250,
+ "opcode": "NAME_PREORDER",
+ "preorder_hash": "386e2de88a908ad056361e586faa95852be454ca",
+ "sender": "76a91407830f81167f6a2aa253c0f176b7ff2e1c04c61a88ac",
+ "sender_pubkey": "03b7795d33b362338179e5b2a579431b285f6c303d07ddd83c897277be4e5eb916",
+ "txid": "4dd315ad1d1b318614a19e15e767efb7ef327bd5cd4ebaf8f80ede58fd1da107",
+ "vtxindex": 174
+ },
+ {
+ "address": "17QEd6rrhNZp4xoyWu6BpA8NQ4axyNKaZy",
+ "block_number": 462592,
+ "burn_address": "1111111111111111111114oLvT2",
+ "consensus_hash": "d206b2f615de00803402cade4d0d51d4",
+ "op": "?",
+ "op_fee": 6250,
+ "opcode": "NAME_PREORDER",
+ "preorder_hash": "a7a388a2bbe0e7741c6cfdc54d7b5a67811cd582",
+ "sender": "76a9144635b1794a22bfbe6c5c5eba17b693f4aaf0e34888ac",
+ "sender_pubkey": "020d6e50b2660af27933c42bc1395fe93df90ffac5e2a989f6a134919fb8cf8075",
+ "txid": "51d6bd117da5889e710c62967d03233a84fc27f7fad10ca4359111928818f017",
+ "vtxindex": 332
+ },
+ {
+ "address": "15YMyvqz6v9ATSbmqJnudwrdm7RiVfkU3s",
+ "block_number": 462453,
+ "consensus_hash": "f6491e1d2b9817fa58512fc9bf8cd3df",
+ "first_registered": 462575,
+ "importer": null,
+ "importer_address": null,
+ "keep_data": true,
+ "last_renewed": 462575,
+ "name": "ablankstein.id",
+ "name_hash128": "943b8e0613d975c05a05ccd5472e2a72",
+ "namespace_block_number": 373601,
+ "namespace_id": "id",
+ "op": ">>",
+ "op_fee": 25000,
+ "opcode": "NAME_TRANSFER",
+ "preorder_block_number": 462453,
+ "preorder_hash": "822d5cb6f2e3f0f901d6af8c1111ee466b6c07bd",
+ "revoked": false,
+ "sender": "76a91431cee995f242f0f66518080a291714cd7e8d2f5e88ac",
+ "sender_pubkey": null,
+ "txid": "121540e81223c45d139fbe03a9713ddd292372f2f88fe2b10b6a7c5e6738e87f",
+ "value_hash": "96ec93cbc57d17b16a347c11ddfa7ea88d2cf93b",
+ "vtxindex": 633
+ },
+ {
+ "address": "1Dwq9oA5BNz7DAR1LtDncEa647ZxgmkoVV",
+ "block_number": 462325,
+ "consensus_hash": "1288cef43f52bf97e2f458a4afe40b61",
+ "first_registered": 462359,
+ "importer": null,
+ "importer_address": null,
+ "keep_data": true,
+ "last_renewed": 462359,
+ "name": "fpenrose.id",
+ "name_hash128": "7af28a9834934a0af81a19ee14a45f8e",
+ "namespace_block_number": 373601,
+ "namespace_id": "id",
+ "op": ">>",
+ "op_fee": 25000,
+ "opcode": "NAME_TRANSFER",
+ "preorder_block_number": 462325,
+ "preorder_hash": "59c25d7cddf433b5122cabcbf2ebcc1bc1519e4d",
+ "revoked": false,
+ "sender": "76a9148e002a93b9b1936b5d320967194eaff3deaa979088ac",
+ "sender_pubkey": null,
+ "txid": "6461bb4bbf517e9c80ffcac4c349836972656572e113aba736b356119655064e",
+ "value_hash": "ac73155702ca7aea1161d0f0c7877ac81d48d8fc",
+ "vtxindex": 637
+ },
+ {
+ "address": "1Q44Md5KFr6gxQ6TdUSFaCRm3MaUyXMF6t",
+ "block_number": 462316,
+ "consensus_hash": "1288cef43f52bf97e2f458a4afe40b61",
+ "first_registered": 462353,
+ "importer": null,
+ "importer_address": null,
+ "keep_data": true,
+ "last_renewed": 462353,
+ "name": "rahulpradhan.id",
+ "name_hash128": "c55ff9e14c72b2950b14ff10067d7e27",
+ "namespace_block_number": 373601,
+ "namespace_id": "id",
+ "op": ">>",
+ "op_fee": 25000,
+ "opcode": "NAME_TRANSFER",
+ "preorder_block_number": 462316,
+ "preorder_hash": "fcb3389ca4d2ab8003ce8b6b3baa0a5ae1600cce",
+ "revoked": false,
+ "sender": "76a914fcdef125f40f984fafad4b58e30e3b1761a953f388ac",
+ "sender_pubkey": null,
+ "txid": "be58e02642c457fec2835a354fbc2de45e8c838aa5b7fd18ed831f67d08269e6",
+ "value_hash": "e213e58ca1446875b79d866720130cc90cbca681",
+ "vtxindex": 638
+ },
+ {
+ "address": "1D8pL725X9HWvoTVgzqDNbTPayHGG7tkY6",
+ "block_number": 462345,
+ "consensus_hash": "919df884f14f34fd15a791af2fddb569",
+ "first_registered": 462380,
+ "importer": null,
+ "importer_address": null,
+ "keep_data": true,
+ "last_renewed": 462380,
+ "name": "sajithskurup.id",
+ "name_hash128": "3fda1c60620c42e1ede385bb246bd5f0",
+ "namespace_block_number": 373601,
+ "namespace_id": "id",
+ "op": ">>",
+ "op_fee": 25000,
+ "opcode": "NAME_TRANSFER",
+ "preorder_block_number": 462345,
+ "preorder_hash": "540daefe1f3b520253f7ab954dbc8bf131471133",
+ "revoked": false,
+ "sender": "76a914851bee0185dd799755234fb20710a26ec40354d288ac",
+ "sender_pubkey": null,
+ "txid": "e7d35196ca3eec697274d848136f5267b1c935055a917020f93e8ecaf821ba99",
+ "value_hash": "92534954e934019718478bb52150765dfad79171",
+ "vtxindex": 644
+ },
+ {
+ "address": "1EbjXtYv9QCVBp8iWiDH6xQ1B74oFW696X",
+ "block_number": 462345,
+ "consensus_hash": "e0c31e03125f2feefd4090e5c635ee45",
+ "first_registered": 462380,
+ "importer": null,
+ "importer_address": null,
+ "keep_data": true,
+ "last_renewed": 462380,
+ "name": "hubject.id",
+ "name_hash128": "03e8bf92dd3cbde65cac012350efb79d",
+ "namespace_block_number": 373601,
+ "namespace_id": "id",
+ "op": ">>",
+ "op_fee": 25000,
+ "opcode": "NAME_TRANSFER",
+ "preorder_block_number": 462345,
+ "preorder_hash": "ded4d097614cf5321388bbe56b24d3d592b2ef76",
+ "revoked": false,
+ "sender": "76a914952b4844005dd98a1f7fc99813db2a649109b45988ac",
+ "sender_pubkey": null,
+ "txid": "7b7a2a2963f7454b93003031cfce64ac609f902b4c2cababfbbfad2c01bbeb9b",
+ "value_hash": "be968a1f17ac828179e5b2fbc70d238056af7482",
+ "vtxindex": 645
+ },
+ {
+ "address": "14YsDo5qgAP7kmnq33tw9JdHVBywpg9pge",
+ "block_number": 462326,
+ "consensus_hash": "e0c31e03125f2feefd4090e5c635ee45",
+ "first_registered": 462354,
+ "importer": null,
+ "importer_address": null,
+ "keep_data": true,
+ "last_renewed": 462354,
+ "name": "ramimassoud.id",
+ "name_hash128": "61a48b6f8aeb027883ecd1f8d808c8ac",
+ "namespace_block_number": 373601,
+ "namespace_id": "id",
+ "op": ">>",
+ "op_fee": 25000,
+ "opcode": "NAME_TRANSFER",
+ "preorder_block_number": 462326,
+ "preorder_hash": "23aa275e42d7d6d7e538584a799252939687c457",
+ "revoked": false,
+ "sender": "76a91426ef31b7aac60eff23cbbab51d453b84700e330388ac",
+ "sender_pubkey": null,
+ "txid": "85babcf66caf41cb7beb2e637cbed4e728ab8030337fb5df8461d0e14dd2be75",
+ "value_hash": "e27c9c3dcce8a8445d84fb8b4d81fbd30fac9749",
+ "vtxindex": 646
+ },
+ {
+ "address": "1H934mT7AVVZmHwjddUZ9EiostLwm655oF",
+ "block_number": 462345,
+ "consensus_hash": "919df884f14f34fd15a791af2fddb569",
+ "first_registered": 462391,
+ "importer": null,
+ "importer_address": null,
+ "keep_data": true,
+ "last_renewed": 462391,
+ "name": "was2bme.id",
+ "name_hash128": "f2b5688682fd47b8f3fbf709bb35ef33",
+ "namespace_block_number": 373601,
+ "namespace_id": "id",
+ "op": ">>",
+ "op_fee": 6250,
+ "opcode": "NAME_TRANSFER",
+ "preorder_block_number": 462345,
+ "preorder_hash": "3dfdcee2b0e64697c4bb0b0dd791518bcb078dc7",
+ "revoked": false,
+ "sender": "76a914b107105f8ae57e7bb5bad58caba666faa679c70f88ac",
+ "sender_pubkey": null,
+ "txid": "16171e4e20778354a94c5353b0c6ed0b29a3e73c1b59b9bfbcbe6d26c570fd0c",
+ "value_hash": "ac73155702ca7aea1161d0f0c7877ac81d48d8fc",
+ "vtxindex": 649
+ },
+ {
+ "address": "1B4zxvVMPm1PBGarc8PrYQjQY2ezwniyG6",
+ "block_number": 462345,
+ "consensus_hash": "e0c31e03125f2feefd4090e5c635ee45",
+ "first_registered": 462391,
+ "importer": null,
+ "importer_address": null,
+ "keep_data": true,
+ "last_renewed": 462391,
+ "name": "tadas_serbenta.id",
+ "name_hash128": "6d800932daf830925ab47dee5ceb8661",
+ "namespace_block_number": 373601,
+ "namespace_id": "id",
+ "op": ">>",
+ "op_fee": 6250,
+ "opcode": "NAME_TRANSFER",
+ "preorder_block_number": 462345,
+ "preorder_hash": "07a85eac4dbf20000a66a14a4a89a01134b70fab",
+ "revoked": false,
+ "sender": "76a9146e72e44bbe4c1706ea5830096a4bb4449dcc948f88ac",
+ "sender_pubkey": null,
+ "txid": "e3f0b019550417a7acfe27addfbd34ec7ec5fc1dd9616ed8c6bc86a0ad148290",
+ "value_hash": "fbac107ba5d9bbfc30ecdeae3e10ca3db72b3431",
+ "vtxindex": 855
+ },
+ {
+ "address": "16BF35VputeLEmbsk7gDnUcwKXcjwPDUvf",
+ "block_number": 462345,
+ "consensus_hash": "919df884f14f34fd15a791af2fddb569",
+ "first_registered": 462359,
+ "importer": null,
+ "importer_address": null,
+ "keep_data": true,
+ "last_renewed": 462359,
+ "name": "alexucf.id",
+ "name_hash128": "d9bc88b0fdc536e7ac5467609faed518",
+ "namespace_block_number": 373601,
+ "namespace_id": "id",
+ "op": ">>",
+ "op_fee": 25000,
+ "opcode": "NAME_TRANSFER",
+ "preorder_block_number": 462345,
+ "preorder_hash": "30f841114af6ada90ba720d563672113c4f74439",
+ "revoked": false,
+ "sender": "76a91438c8814ae2a9035e85bbf2b7976919c2e3387ac588ac",
+ "sender_pubkey": null,
+ "txid": "f8e9eebd48b9182b82b22e5ce10f805d3db38786bb2aaf56f9badf83aa3cc0ee",
+ "value_hash": "8ae0f51263f540be175230d6b46f5d9609de799d",
+ "vtxindex": 856
+ },
+ {
+ "address": "1EmXTRHC6f9bnLJkVZRavv7HLG1owLgNir",
+ "block_number": 462326,
+ "consensus_hash": "31a304b682e3291811441a12f19d14e5",
+ "first_registered": 462391,
+ "importer": null,
+ "importer_address": null,
+ "keep_data": true,
+ "last_renewed": 462391,
+ "name": "seamur.id",
+ "name_hash128": "09f3b9d2da3d0aa1999824f7884f0d18",
+ "namespace_block_number": 373601,
+ "namespace_id": "id",
+ "op": ">>",
+ "op_fee": 100000,
+ "opcode": "NAME_TRANSFER",
+ "preorder_block_number": 462326,
+ "preorder_hash": "678991fd4d3833babe27f732206a40d1f15dd3ca",
+ "revoked": false,
+ "sender": "76a91497055c47fa0ab396fb321e9d37f6bce1796e3d5688ac",
+ "sender_pubkey": null,
+ "txid": "e32124770c359eaf57709e5a666894f2954aa687820c41c6911f214e9006b58e",
+ "value_hash": "4bcdd931185537902ef1af9975198c6404d4c73e",
+ "vtxindex": 857
+ },
+ {
+ "address": "13pGtMcHsNdq3EeLMa1yVVKppP1WjSKgFG",
+ "block_number": 462345,
+ "consensus_hash": "e0c31e03125f2feefd4090e5c635ee45",
+ "first_registered": 462354,
+ "importer": null,
+ "importer_address": null,
+ "keep_data": true,
+ "last_renewed": 462354,
+ "name": "innergame.id",
+ "name_hash128": "a3e4e010d82369ee19b64fccc2b97f69",
+ "namespace_block_number": 373601,
+ "namespace_id": "id",
+ "op": ">>",
+ "op_fee": 25000,
+ "opcode": "NAME_TRANSFER",
+ "preorder_block_number": 462345,
+ "preorder_hash": "f54850caf10c3041cb2a4d9186bbb234dd7d9f85",
+ "revoked": false,
+ "sender": "76a9141ee10ff0ae9969e2dc39d94a959e3160b26b6adf88ac",
+ "sender_pubkey": null,
+ "txid": "28de7193e28e1b0c950a32af393284578669c15dc98bad68f382f8b920d94509",
+ "value_hash": "bab40c2b10f676288edea119edade67ff5e853ba",
+ "vtxindex": 869
+ }
+ ]
+
+ + Schema
+
+ {
+ 'type': 'array',
+ 'items': {
+ 'type': 'object',
+ 'properties': {
+ 'address': {
+ 'type': 'string',
+ 'pattern': "^([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]+)$",
+ },
+ 'base': {
+ 'type': 'integer',
+ 'minimum': 0,
+ 'maximum': 255,
+ },
+ 'buckets': {
+ 'anyOf': [
+ {
+ 'type': 'array',
+ 'items': {
+ 'type': 'integer',
+ 'minItems': 16,
+ 'maxItems': 16,
+ },
+ },
+ {
+ 'type': 'null',
+ },
+ ],
+ },
+ 'block_number': {
+ 'type': 'integer',
+ 'minimum': 0,
+ },
+ 'coeff': {
+ 'anyOf': [
+ {
+ 'type': 'integer',
+ 'minimum': 0,
+ 'maximum': 255,
+ },
+ {
+ 'type': 'null'
+ },
+ ],
+ },
+ 'consensus_hash': {
+ 'anyOf': [
+ {
+ 'type': 'string',
+ 'pattern': '^[0-9a-fA-F]{32}',
+ },
+ {
+ 'type': 'null'
+ },
+ ],
+ },
+ 'domain': {
+ 'type': 'string',
+ 'pattern': '^([a-z0-9\-_.+]{3,37})$',
+ },
+ 'fee': {
+ 'type': 'integer',
+ 'minimum': 0,
+ },
+ 'first_registered': {
+ 'type': 'integer',
+ 'minimum': 0,
+ },
+ 'history_snapshot': {
+ 'type': 'boolean',
+ },
+ 'importer': {
+ 'anyOf': [
+ {
+ 'type': 'string',
+ 'pattern': '^76[aA]914[0-9a-fA-F]{40}88[aA][cC]$',
+ },
+ {
+ 'type': 'null',
+ },
+ ],
+ },
+ 'importer_address': {
+ 'anyOf': [
+ {
+ 'type': 'string',
+ 'pattern': "^([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]+)$",
+ },
+ {
+ 'type': 'null',
+ },
+ ],
+ },
+ 'last_renewed': {
+ 'type': 'integer',
+ 'minimum': 0,
+ },
+ 'name': {
+ 'type': 'string',
+ 'pattern': '^([a-z0-9\\-_.+]{3,37})\.([a-z0-9\\-_.+]{3,37})$',
+ },
+ 'op': {
+ 'type': 'string',
+ 'pattern': '^([>?+~:!&*:;#]{1}|>>|>~|::)$',
+ },
+ 'op_fee': {
+ 'type': 'number',
+ },
+ 'opcode': {
+ 'type': 'string',
+ 'pattern': '^NAME_TRANSFER|NAME_PREORDER|NAME_UPDATE|NAME_REVOKE|NAME_REGISTRATION|NAMESPACE_READY|NAMESPACE_REVEAL|NAMESPACE_PREORDER|NAME_RENEWAL|NAME_IMPORT|ANNOUNCE$'
+ },
+ 'revoked': {
+ 'type': 'boolean',
+ },
+ 'sender': {
+ 'type': 'string',
+ 'pattern': '^([0-9a-fA-F]+)$',
+ },
+ 'sender_pubkey': {
+ 'anyOf': [
+ {
+ 'type': 'string',
+ 'pattern': '^([0-9a-fA-F]+)$',
+ },
+ {
+ 'type': 'null'
+ },
+ ],
+ },
+ 'sequence': {
+ 'type': 'integer',
+ 'minimum': 0
+ }
+ 'recipient': {
+ 'anyOf': [
+ {
+ 'type': 'string',
+ 'pattern': '^([0-9a-fA-F]+)$',
+ },
+ {
+ 'type': 'null'
+ },
+ ],
+ },
+ 'recipient_address': {
+ 'anyOf': [
+ {
+ 'type': 'string',
+ 'pattern': '^([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]+)$',
+ },
+ {
+ 'type': 'null'
+ },
+ ],
+ },
+ 'recipient_pubkey': {
+ 'anyOf': [
+ {
+ 'type': 'string',
+ 'pattern': '^([0-9a-fA-F]+)$',
+ },
+ {
+ 'type': 'null'
+ },
+ ],
+ },
+ 'txid': {
+ 'type': 'string',
+ 'pattern': '^([0-9a-fA-F]+)$',
+ },
+ 'value_hash': {
+ 'anyOf': [
+ {
+ 'type': 'string',
+ 'pattern': '^([0-9a-fA-F]{40})$',
+ },
+ {
+ 'type': 'null',
+ },
+ ],
+ },
+ 'vtxindex': {
+ 'type': 'integer',
+ 'minimum': 0,
+ },
+ },
+ 'required': [
+ 'txid',
+ 'vtxindex'
+ ],
+ }
+ }
+ }
+
++ Response 400 (application/json)
+ + Body
+
+ { "error": "Invalid name or subdomain" }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'error': { 'type': 'string' },
+ },
+ }
+
++ Response 404 (application/json)
+ + Body
+
+ { "error": "No such name" }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'error': { 'type': 'string' },
+ },
+ }
+
+# Group Namespace Operations
+
+## Get all namespaces [GET /v1/namespaces]
++ Public Endpoint
++ Response 200 (application/json)
+ + Body
+
+ {
+ "namespaces": [
+ "id"
+ ]
+ }
+
+ + Schema
+ {
+ 'type': 'object',
+ 'properties': {
+ 'namespaces': {
+ 'type': 'array',
+ 'items': { 'type': 'string' }
+ }
+ },
+ 'required': [ 'namespaces' ]
+ }
+
+## Get namespace names [GET /v1/namespaces/{tld}/names?page={page}]
+
+Fetch a list of names from the namespace.
++ Public Endpoint
++ Parameters
+ + tld: id (string) - the namespace to fetch names from
+ + page: 23 (number) - names are returned in pages of size 100,
+ so specify the page number.
++ Response 200 (application/json)
+ + Body
+
+ [ "aldenquimby.id", "aldeoryn.id",
+ "alderete.id", "aldert.id",
+ "aldi.id", "aldighieri.id", ... ]
+
+ + Schema
+
+ {
+ 'type': 'array',
+ 'items': {
+ 'type': 'string',
+ 'pattern': '^([a-z0-9\-_.+]{3,37})$'
+ }
+ }
+
++ Response 400 (application/json)
+ + Body
+
+ { "error": "Invalid page" }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'error': { 'type': 'string' },
+ },
+ }
+
++ Response 404 (application/json)
+ + Body
+
+ { "error": "No such namespace" }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'error': { 'type': 'string' },
+ },
+ }
+
+# Group Resolver Endpoints
+
+## Lookup User [GET /v1/users/{username}]
+Lookup and resolver a user's profile. Defaults to the `id` namespace.
+Note that [blockstack.js](https://github.com/blockstack/blockstack.js) does
+*not* rely on this endpoint.
+
++ Public Endpoint
++ Subdomain Aware
++ Legacy Endpoint
++ Parameters
+ + username: fred (string) - username to lookup
++ Response 200 (application/json)
+
+ {
+ "fred.id": {
+ "owner_address": "1CER5u4QXuqffHjHKrU76iMCsqtJLM5VHu",
+ "profile": {
+ "@context": "http://schema.org",
+ "@type": "Person",
+ "account": [
+ {
+ "@type": "Account",
+ "identifier": "fredwilson",
+ "placeholder": false,
+ "proofType": "http",
+ "proofUrl": "https://twitter.com/fredwilson/status/943066895422455809",
+ "service": "twitter"
+ }
+ ],
+ "description": "I am a VC",
+ "image": [
+ {
+ "@type": "ImageObject",
+ "contentUrl": "https://gaia.blockstack.org/hub/1CER5u4QXuqffHjHKrU76iMCsqtJLM5VHu/0/avatar-0",
+ "name": "avatar"
+ }
+ ],
+ "name": "Fred Wilson"
+ },
+ "public_key": "026c94d1897fa148fa6401247a339b55abd869a3d562fdae8a7fcb9a11f1f846f3",
+ "verifications": [
+ {
+ "identifier": "fredwilson",
+ "proof_url": "https://twitter.com/fredwilson/status/943066895422455809",
+ "service": "twitter",
+ "valid": true
+ }
+ ],
+ "zone_file": {
+ "$origin": "fred.id",
+ "$ttl": 3600,
+ "uri": [
+ {
+ "name": "_http._tcp",
+ "priority": 10,
+ "target": "https://gaia.blockstack.org/hub/1CER5u4QXuqffHjHKrU76iMCsqtJLM5VHu/0/profile.json",
+ "weight": 1
+ }
+ ]
+ }
+ }
+ }
+
+ + Schema
+ {
+ 'type': 'object',
+ 'patternProperties': {
+ '^([a-z0-9\\-_.+]{3,37})\.([a-z0-9\\-_.+]{3,37})$|^([a-z0-9\\-_.+]){3,37}$': {
+ 'type': 'object',
+ 'properties': {
+ 'owner_address': { 'type': 'string', 'pattern': "^([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]+)$" },
+ 'profile' : { 'type': 'object' },
+ 'public_key': { 'type': 'string', 'pattern': "^([0-9a-fA-F]$" },
+ 'verifications: {
+ 'type': 'array',
+ 'items': {
+ 'type': 'object',
+ 'properties': {
+ 'identifier': { 'type': 'string' },
+ 'proof_url': { 'type': 'string' },
+ 'service': { 'type': 'string' },
+ 'valid': { 'type': 'boolean' }
+ },
+ }
+ },
+ 'zone-file': { 'type': 'object' }
+ }
+ }
+ }
+ }
+
++ Response 404 (application/json)
+ + Body
+
+ {
+ "nope.none": {
+ "error": "Name has no user record hash defined"
+ }
+ }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'patternProperties': {
+ '^([a-z0-9\\-_.+]{3,37})\.([a-z0-9\\-_.+]{3,37})$|^([a-z0-9\\-_.+]){3,37}$': {
+ 'type': 'object',
+ 'properties': {
+ 'error': { 'type': 'string' }
+ },
+ 'required': [ 'error' ]
+ }
+ }
+ }
+
+## Profile Search [GET /v1/search?query={query}]
+Searches for a profile using a search string.
++ Public Only Endpoint
++ Parameters
+ + query: wenger (string) - the search query
++ Response 200 (application/json)
+ + Body
+
+ {
+ "results": [
+ {
+ "fullyQualifiedName": "albertwenger.id",
+ "username": "albertwenger",
+ "profile": {
+ "@type": "Person",
+ "account": [
+ {
+ "@type": "Account",
+ "identifier": "albertwenger",
+ "proofType": "http",
+ "service": "twitter"
+ },
+ {
+ "@type": "Account",
+ "identifier": "albertwenger",
+ "proofType": "http",
+ "service": "facebook"
+ },
+ {
+ "@type": "Account",
+ "identifier": "albertwenger",
+ "proofType": "http",
+ "service": "github"
+ },
+ {
+ "@type": "Account",
+ "identifier": "1QHDGGLEKK7FZWsBEL78acV9edGCTarqXt",
+ "role": "payment",
+ "service": "bitcoin"
+ }
+ ],
+ "address": {
+ "@type": "PostalAddress",
+ "addressLocality": "New York"
+ },
+ "description": "VC at USV.com",
+ ...
+ }
+
+ + Schema
+ {
+ 'type': 'object',
+ 'properties': {
+ 'results': {
+ 'type': 'array',
+ 'items': {
+ 'fullyQualifiedName': { 'type': 'string', 'pattern': '^([a-z0-9\\-_.+]{3,37})\.([a-z0-9\\-_.+]{3,37})$|^([a-z0-9\\-_.+]){3,37}$' },
+ 'username': { 'type': 'string' },
+ 'profile' : { 'type': 'object' },
+ }
+ }
+ }
+ }
+
diff --git a/_core/.svn/pristine/83/83e8050e14038cc52734e14bf1d1bd165582b6ad.svn-base b/_core/.svn/pristine/83/83e8050e14038cc52734e14bf1d1bd165582b6ad.svn-base
new file mode 100644
index 00000000..cc4a5359
--- /dev/null
+++ b/_core/.svn/pristine/83/83e8050e14038cc52734e14bf1d1bd165582b6ad.svn-base
@@ -0,0 +1,3 @@
+Documentation for setting up the regtest mode for Blockstack Browser
+using core's integration tests in macOS and Linux has
+moved [here](../integration_tests).
diff --git a/_core/.svn/pristine/92/92f5cb4f22680e651c684bca0a71854eb82b91bd.svn-base b/_core/.svn/pristine/92/92f5cb4f22680e651c684bca0a71854eb82b91bd.svn-base
new file mode 100644
index 00000000..92851cb5
--- /dev/null
+++ b/_core/.svn/pristine/92/92f5cb4f22680e651c684bca0a71854eb82b91bd.svn-base
@@ -0,0 +1,604 @@
+---
+layout: core
+permalink: /:collection/:path.html
+---
+# Create and Launch a Namespace
+{:.no_toc}
+
+This tutorial teaches you how to create your namespace, it contains the
+following sections:
+
+* TOC
+{:toc}
+
+
+Creating namespaces is expensive.
+Be sure to test your namespace in our [integration test
+framework](https://github.com/blockstack/blockstack-core/tree/master/integration_tests)
+first! It will let you simulate any valid namespace configuration
+you want at no risk to you.
+
+
+>**WARNING**: If you intend to create a namespace, you must read this document
+_in its entirety_. You should also _install the test framework_ and experiment
+with your namespace's parameters. _FAILURE TO DO SO MAY RESULT IN IRRECOVERABLE
+LOSS OF FUNDS._
+
+## Before you begin
+
+Some basic familiarity with how Bitcoin works is required to
+understand this tutorial. This includes:
+
+* knowing the difference between mainnet, testnet, and regtest
+* knowing about compressed and uncompressed ECDSA public keys
+* knowing about base58-check encoding
+* knowing how Bitcoin transactions are structured
+* knowing how UTXOs work
+
+Creating a namespace is a three-step process. The first step is to `preorder`
+the namespace, which broadcasts a salted hash of the namespace ID. The second
+step is to `reveal` the namespace, which exposes the namespace ID and price
+function to the blockchain. The final step is to `ready` the namespace, which
+allows anyone to register names within it.
+
+In between the `reveal` and `ready` steps, the namespace creator will have a
+"lock" on the namespace that lasts for about 1 year. During this time period,
+the namespace creator can `import` names. The `import` transaction lets the
+namespace creator assign the name a zone file and an owner in one step.
+
+## Before Trying This in Production...
+
+
+
+### Setting up the Test Environment
+
+In this example, we will use the test framework to create a private Bitcoin
+blockchain on your computer, and then create a Blockstack namespace on it.
+This will let you experiment with different namespace parameters
+without spending actual BTC. The test framework uses `bitcoind -regtest`,
+so all of the commands you'll run here will work identically on
+mainnet.
+
+To install the test framework, please follow these
+[instructions](https://github.com/blockstack/blockstack-core/tree/master/integration_tests).
+Once you have the test framework installed, you should run the `namespace_check` test in `--interactive-web` mode.
+This will create an empty `.test` namespace and leave the test scenario running
+once it finishes. You will be able to fund addresses and create new blocks via
+your Web browser or via `curl`, as will be explained below. Also, you'll be able to use the
+`blockstack` utility to interact with your private blockchain and namespaces.
+
+The test setup command is as follows. This will launch the `namespace_check`
+test scenario, and open a web server on port 3001.
+```bash
+ $ blockstack-test-scenario --interactive-web 3001 blockstack_integration_tests.scenarios.namespace_check
+```
+
+When the test is ready for us to experiment, you should see the following:
+
+```bash
+ An empty namespace called 'test' has been created
+ Feel free to experiment with other namespaces
+
+ Available keys with a balance:
+ * 6e50431b955fe73f079469b24f06480aee44e4519282686433195b3c4b5336ef01
+ * c244642ce0b4eb68da8e098facfcad889e3063c36a68b7951fb4c085de49df1b01
+ * f4c3907cb5769c28ff603c145db7fc39d7d26f69f726f8a7f995a40d3897bb5201
+ * 8f87d1ea26d03259371675ea3bd31231b67c5df0012c205c154764a124f5b8fe01
+ * bb68eda988e768132bc6c7ca73a87fb9b0918e9a38d3618b74099be25f7cab7d01
+ * 2,3,6f432642c087c2d12749284d841b02421259c4e8178f25b91542c026ae6ced6d01,65268e6267b14eb52dc1ccc500dc2624a6e37d0a98280f3275413eacb1d2915d01,cdabc10f1ff3410082448b708c0f860a948197d55fb612cb328d7a5cc07a6c8a01
+ * 2,3,4c3ab2a0704dfd9fdc319cff2c3629b72ebda1580316c7fddf9fad1baa323e9601,75c9f091aa4f0b1544a59e0fce274fb1ac29d7f7e1cd020b66f941e5d260617b01,d62af1329e541871b244c4a3c69459e8666c40b683ffdcb504aa4adc6a559a7701
+ * 2,3,4b396393ca030b21bc44a5eba1bb557d04be1bfe974cbebc7a2c82b4bdfba14101,d81d4ef8123852403123d416b0b4fb25bcf9fa80e12aadbc08ffde8c8084a88001,d0482fbe39abd9d9d5c7b21bb5baadb4d50188b684218429f3171da9de206bb201
+ * 2,3,836dc3ac46fbe2bcd379d36b977969e5b6ef4127e111f2d3e2e7fb6f0ff1612e01,1528cb864588a6a5d77eda548fe81efc44180982e180ecf4c812c6be9788c76a01,9955cfdac199b8451ccd63ec5377a93df852dc97ea01afc47db7f870a402ff0501
+```
+
+You can determine that the test framework is live by going to
+`http://localhost:3001` in your Web browser. From there, you can generate
+blocks in the test framework's `bitcoind` node and you can fund any address in
+the test framework.
+
+Finally, you can use the `blockstack-test-env` command to set up your shell
+environment variables so `blockstack` will interact with this test (instead of
+mainnet). To do so, run the following in your shell:
+
+```bash
+ $ . $(which blockstack-test-env) namespace_check
+ |blockstack-test namespace_check| $
+```
+
+You can verify that the environment variables by verifying that your `$PS1`
+variable includes the name of your test (as shown above), and that some other
+`BLOCKSTACK_`-prefixed variables are set:
+
+```bash
+ |blockstack-test namespace_check| $ env | grep BLOCKSTACK
+ BLOCKSTACK_OLD_PS1=\u@\h:\w$
+ BLOCKSTACK_TESTNET=1
+ BLOCKSTACK_EPOCH_1_END_BLOCK=1
+ BLOCKSTACK_EPOCH_2_END_BLOCK=2
+ BLOCKSTACK_TEST=1
+ BLOCKSTACK_DEBUG=1
+ BLOCKSTACK_CLIENT_CONFIG=/tmp/blockstack-run-scenario.blockstack_integration_tests.scenarios.namespace_check/client/client.ini
+```
+
+## Registering a Namespace
+
+Suppose we're going to create the `hello` namespace. The key
+`6e50431b955fe73f079469b24f06480aee44e4519282686433195b3c4b5336ef01` will be the key that
+*pays* for the namespace. The key
+`c244642ce0b4eb68da8e098facfcad889e3063c36a68b7951fb4c085de49df1b01` will be the key that
+*creates* the namespace. The creator key will be used to `import` names and
+declare the namespace `ready`. The payment key will be used to both pay for the
+namespace and receive name registration and renewal fees for the first year of
+the namespace's lifetime.
+
+In this example, we will set these keys as environment variables:
+
+```bash
+ |blockstack-test namespace_check| $ export PAYMENT_PKEY="6e50431b955fe73f079469b24f06480aee44e4519282686433195b3c4b5336ef01"
+ |blockstack-test namespace_check| $ export CREATOR_PKEY="c244642ce0b4eb68da8e098facfcad889e3063c36a68b7951fb4c085de49df1b01"
+```
+
+#### Multisig Namespace Payment
+
+If you want to use a multisig address to pay for your namespace (and collect
+name registration fees), then instead of using
+`6e50431b955fe73f079469b24f06480aee44e4519282686433195b3c4b5336ef01`, you should
+use a string formatted as `m,n,pk1,pk2,...,pk_n`. `m` is the number of
+signatures required, `n` is the number of private keys, and `pk1,pk2,...,pk_n`
+are the private keys.
+
+For example, you can use the following as your `PAYMENT_PKEY` to have a 2-of-3
+multisig script pay for your namespace and collect name registration fees:
+
+```bash
+ |blockstack-test namespace_check| $ export PAYMENT_PKEY="2,3,6f432642c087c2d12749284d841b02421259c4e8178f25b91542c026ae6ced6d01,65268e6267b14eb52dc1ccc500dc2624a6e37d0a98280f3275413eacb1d2915d01,cdabc10f1ff3410082448b708c0f860a948197d55fb612cb328d7a5cc07a6c8a01"
+```
+
+### Namespace preorder
+
+The command to preorder the namespace would be:
+
+```bash
+ |blockstack-test namespace_check| $ blockstack namespace_preorder hello "$PAYMENT_PKEY" "$CREATOR_PKEY"
+```
+
+You will be given a set of instructions on how to proceed to reveal and
+launch the namespace. _READ THEM CAREFULLY_. You will be prompted to
+explicitly acknowledge that you understand the main points of the instructions,
+and that you understand the risks.
+
+The command outputs some necessary information at the very end of its execution.
+In particular, you will need to remember the transaction ID of the namespace
+preorder. The command will help you do so.
+
+Here is a sample output:
+
+```bash
+ |blockstack-test namespace_check| $ blockstack namespace_preorder hello "$PAYMENT_PKEY" "$CREATOR_PKEY"
+
+ <...snip...>
+
+ Remember this transaction ID: b40dd1375ef63e5a40ee60d790ec6dccd06efcbac99d0cd5f3b07502a4ab05ac
+ You will need it for `blockstack namespace_reveal`
+
+ Wait until b40dd1375ef63e5a40ee60d790ec6dccd06efcbac99d0cd5f3b07502a4ab05ac has six (6) confirmations. Then, you can reveal `hello` with:
+
+ $ blockstack namespace_reveal "hello" "6e50431b955fe73f079469b24f06480aee44e4519282686433195b3c4b5336ef01" "c244642ce0b4eb68da8e098facfcad889e3063c36a68b7951fb4c085de49df1b01" "b40dd1375ef63e5a40ee60d790ec6dccd06efcbac99d0cd5f3b07502a4ab05ac"
+
+ {
+ "status": true,
+ "success": true,
+ "transaction_hash": "b40dd1375ef63e5a40ee60d790ec6dccd06efcbac99d0cd5f3b07502a4ab05ac"
+ }
+```
+
+If all goes well, you will get back a transaction hash (in this case, `b40dd1375ef63e5a40ee60d790ec6dccd06efcbac99d0cd5f3b07502a4ab05ac`).
+To get Blockstack to process it, you will need to mine some blocks in the test framework (by default,
+Blockstack will only accept a transaction that has 6 confirmations). To do
+this, simply go to `http://localhost:3001` and generate at least 6 blocks. If you
+observe the test log, you will see the Blockstack node process and accept it.
+
+Note that when you do this live, you should wait for
+at least 10 confirmations before sending the `reveal` transaction, just to be
+safe.
+
+### Namespace reveal
+
+The command to reveal a preordered namespace is more complicated, since it
+describes the price curve.
+
+This command is **interactive**. The command to invoke it is as follows:
+
+```bash
+ |blockstack-test namespace_check| $ blockstack namespace_reveal hello "$PAYMENT_PKEY" "$CREATOR_PKEY" "b40dd1375ef63e5a40ee60d790ec6dccd06efcbac99d0cd5f3b07502a4ab05ac"
+```
+
+When running the command, you will see the namespace creation wizard prompt you
+with the price curve and the current values:
+
+```
+Name lifetimes (blocks): infinite
+Price coefficient: 4
+Price base: 4
+Price bucket exponents: [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
+Non-alpha discount: 2
+No-vowel discount: 5
+Burn or receive fees? Receive to mr6nrMvvh44sR5MiX929mMXP5hqgaTr6fx
+
+Name price formula:
+(UNIT_COST = 10.0 satoshi):
+ buckets[min(len(name)-1, 15)]
+ UNIT_COST * coeff * base
+cost(name) = -----------------------------------------------------
+ max(nonalpha_discount, no_vowel_discount)
+
+
+Name price table:
+| length | price | price, nonalpha | price, no vowel | price, both |
+--------------------------------------------------------------------------
+| 1 | 42949672960 | 8589934592 | 8589934592 | 8589934592 |
+| 2 | 10737418240 | 5368709120 | 2147483648 | 2147483648 |
+| 3 | 2684354560 | 1342177280 | 536870912 | 536870912 |
+| 4 | 671088640 | 335544320 | 134217728 | 134217728 |
+| 5 | 167772160 | 83886080 | 33554432 | 33554432 |
+| 6 | 41943040 | 20971520 | 8388608 | 8388608 |
+| 7 | 10485760 | 5242880 | 2097152 | 2097152 |
+| 8 | 2621440 | 1310720 | 524288 | 524288 |
+| 9 | 655360 | 327680 | 131072 | 131072 |
+| 10 | 163840 | 81920 | 32768 | 32768 |
+| 11 | 40960 | 20480 | 8192 | 8192 |
+| 12 | 10240 | 5120 | 2048 | 2048 |
+| 13 | 2560 | 1280 | 512 | 512 |
+| 14 | 640 | 320 | 128 | 128 |
+| 15 | 160 | 80 | 32 | 32 |
+| 16+ | 40 | 20 | 10 | 10 |
+
+
+What would you like to do?
+(0) Set name lifetime in blocks (positive integer between 1 and 4294967295, or "infinite")
+(1) Set price coefficient (positive integer between 1 and 255)
+(2) Set base price (positive integer between 1 and 255)
+(3) Set price bucket exponents (16 comma-separated integers, each between 1 and 15)
+(4) Set non-alphanumeric character discount (positive integer between 1 and 15)
+(5) Set no-vowel discount (positive integer between 1 and 15)
+(6) Toggle collecting name fees (True: receive fees; False: burn fees)
+(7) Show name price formula
+(8) Show price table
+(9) Done
+
+(1-9)
+```
+
+All prices are in the "fundamental unit" of the underlying blockchain (i.e.
+satoshis).
+
+As the formula describes, the name's price is a function of:
+
+* a fixed unit cost (`UNIT_COST`)
+* a multiplicative constant coefficient (`coeff`)
+* a fixed exponential base (`base`)
+* a 16-element list of price buckets, indexed by the length of the name (`buckets`)
+* a discount for having non-alphnumeric letters (`nonalpha_discount`)
+* a discount for having no vowels in the name (`no_vowel_discount`)
+
+You can use options 1 through 8 to play with the pricing function and examine
+the name costs in the price table. Enter 9 to send the transaction itself.
+
+Once you're happy, you can issue the namespace-reveal transaction. As with the
+namespace-preorder transaction, you will get back a transaction hash, and your transaction will be
+unconfirmed. Simply go to `http://localhost:3001` to generate some more blocks
+to confirm your namespace-reveal.
+
+Once you have confirmed your namespace-reveal transaction, you can
+begin to populate your namespace with some initial names.
+
+**Collecting Name Fees**
+
+Blockstack 0.17 introduced the ability to create a namespace such that for the
+first year of its existence (54595 blocks), all name registration and renewal
+fees will be sent to the address of the _payment key_. In this example,
+this is the address `mr6nrMvvh44sR5MiX929mMXP5hqgaTr6fx`.
+
+The alternative is to
+have all namespace fees sent to an unspendable burn address
+(`1111111111111111111114oLvT2`). This is the case for the `.id` namespace,
+for example.
+
+After the year has passed, all future name registrations and renewal fees
+will be sent to the unspendable burn address. This is to disincentivize
+namespace squatters.
+
+**Warnings**
+
+* You must issue this command **within 144 blocks** of the namespace-preorder transaction. Otherwise, the preorder will expire and you will need to start over from scratch.
+
+### Importing names
+
+After sending the `reveal` transaction, you can populate your namespace with
+some initial names. You can do so with the `name_import` command.
+
+Suppose we want to import the name `example.hello` and assign it to an owner
+whose public key address is `ms6Y32bcL5zhA57e8tf7awgVZuPxV8Xg8N`. Suppose also
+that you wanted to give `example.hello` an initial zone file stored at
+`/var/blockstack/zone_files/example.hello`. To do so, you would issue the
+following command:
+
+```bash
+ |blockstack-test namespace_check| $ blockstack name_import example.hello ms6Y32bcL5zhA57e8tf7awgVZuPxV8Xg8N /var/blockstack/zone_files/example.hello "$CREATOR_PKEY"
+```
+
+By default, you **must** use the private key you used to reveal the namespace
+to import names (this is `$CREATOR_PKEY` in this example).
+
+As with namespace-preorder and namespace-reveal, the transaction this command
+generates will be unconfirmed. Simply go to `http://localhost:3001` to generate
+some blocks to confirm it.
+
+You can check the progress of the transaction with `blockstack info`, as follows:
+
+```bash
+ |blockstack-test namespace_check| $ blockstack info
+ {
+ "cli_version": "0.17.0.8",
+ "consensus_hash": "b10fdd38a20a7e46555ce3a7f68cf95c",
+ "last_block_processed": 694,
+ "last_block_seen": 694,
+ "queues": {
+ "name_import": [
+ {
+ "confirmations": 1,
+ "name": "example.hello",
+ "tx_hash": "10f7dcd9d6963ef5d20d010f731d5d2ddb76163a083b9d7a2b9fd4515c7fe58c"
+ }
+ ]
+ },
+ "server_alive": true,
+ "server_host": "localhost",
+ "server_port": 16264,
+ "server_version": "0.17.0.8"
+ }
+```
+
+The `confirmation` field indicates how deep in the blockchain the transaction is
+at the time. Generating more blocks will increase its number of confirmations.
+
+When you do this live,
+**YOU SHOULD LEAVE YOUR COMPUTER RUNNING UNTIL THE `name_import` QUEUE IS EMPTY**.
+Blockstack's background API daemon will monitor the transactions and upload the
+name's zone file to the Blockstack Atlas network once it is confirmed.
+But to do so, your computer must remain online. If you do not do this, then
+the name will not have a zone file and will be unusable in the higher layers of
+Blockstack-powered software (including Blockstack applications). However,
+if your computer does go offline or reboots, you can recover by
+restarting the Blockstack API daemon (with
+`blockstack api start`). The daemon itself will pick up where it left off, and
+replicate all zone files that have confirmed transactions.
+
+After the zone file is uploaded, the name will be public and resolvable. You can re-import the
+same name over and over, and give it a different address and/or zone file. Like
+all other names, the Blockstack Atlas network will accept and propagate zone
+files for imported names.
+
+The owner of the address `ms6Y32bcL5zhA57e8tf7awgVZuPxV8Xg8N` will **not** be
+able to issue any transactions for the name `example.hello` until the namespace
+creator has sent the `ready` transaction.
+
+#### Using multiple private keys for NAME_IMPORT
+
+Bitcoin itself imposes limits on how fast you can send transactions from the
+same key (limited by a maximum UTXO-chain length). To work around this,
+Blockstack lets you import names by using up to 300 private keys. The private
+keys you can use are BIP32 unhardened children of the namespace reveal key (i.e.
+`$CREATOR_PKEY` in this example).
+
+The first name you import **must** use the namespace reveal private key
+(`$CREATOR_PKEY` in this example). However, all future names you import in this
+namespace can use one of the 300 BIP32 keys.
+
+To get the list of keys you can use, you can use the `make_import_keys` command:
+
+```bash
+ |blockstack-test namespace_check| $ blockstack make_import_keys example hello "$CREATOR_PKEY"
+ aeda50305ada40aaf53f2d8921aa717f1ec71a0a3b9b4c6397b3877f6d45c46501 (n4DVTuLLv5J1Yc17AoRYY1GtxDAuLGAESr)
+ 92ff179901819a1ec7d32997ce3bb0d9a913895d5850cc05146722847128549201 (mib2KNBGR4az8GiUmusBZexVBqb9YB2gm5)
+ cc5b6a454e2b614bfa18f4deb9a8e179ab985634d63b7fedfaa59573472d209b01 (mxE2iqV4jdpn4K349Gy424TvZp6MPqSXve)
+ 9b0265e0ac8c3c24fe1d79a734b3661ec2b5c0c2619bb6342356572b8235910101 (n4rGz8hkXTscUGWCwZvahrkEh6LHZVQUoa)
+ e2585af250404b7918cf6c91c6fa67f3401c0d1ae66df2fafa8fa132f4b9350f01 (moGNpEpighqc6FnkqyNVJA9xtfTiStr5YU)
+ {
+ "status": true
+ }
+```
+
+(NOTE: in the test environment, you get only 5 keys in order to save time).
+
+You can use any of these keys to import names.
+
+#### Trying it out
+
+Here's an example walkthrough of how to try this out in the test framework:
+
+1. Import the first name, creating a zone file in the process:
+
+```bash
+ |blockstack-test namespace_check| $ cat > /var/blockstack/zone_files/example.hello < $ORIGIN example.hello
+ > $TTL 3600
+ > _file URI 10 1 "file:///home/blockstack-test/example.hello"
+ > EOF
+ |blockstack-test namespace_check| $ blockstack name_import example.hello ms6Y32bcL5zhA57e8tf7awgVZuPxV8Xg8N /var/blockstack/zone_files/example.hello "$CREATOR_PKEY"
+ Import cost breakdown:
+ {
+ "name_import_tx_fee": {
+ "btc": 0.0003342,
+ "satoshis": 33420
+ },
+ "total_estimated_cost": {
+ "btc": 0.0003342,
+ "satoshis": 33420
+ },
+ "total_tx_fees": 33420
+ }
+ Importing name 'example.hello' to be owned by 'ms6Y32bcL5zhA57e8tf7awgVZuPxV8Xg8N' with zone file hash '05c302430f4ed0a24470abf9df7e264d517fd389'
+ Proceed? (y/N) y
+ {
+ "status": true,
+ "success": true,
+ "transaction_hash": "bd875f00f63bcb718bb22782c88c3edcbed79663f2f9152deab328c48746f103",
+ "value_hash": "05c302430f4ed0a24470abf9df7e264d517fd389"
+ }
+```
+
+2. Advance the test framework blockchain, so the indexer knows which import keys to expect:
+
+```bash
+ # NOTE: you can also do this by going to http://localhost:3001 in your Web browser
+ |blockstack-test namespace_check| $ curl -X POST http://localhost:3001/nextblock
+```
+
+3. Make import keys:
+
+```bash
+ |blockstack-test namespace_check| $ blocksatck make_import_keys hello "$CREATOR_PKEY"
+ aeda50305ada40aaf53f2d8921aa717f1ec71a0a3b9b4c6397b3877f6d45c46501 (n4DVTuLLv5J1Yc17AoRYY1GtxDAuLGAESr)
+ 92ff179901819a1ec7d32997ce3bb0d9a913895d5850cc05146722847128549201 (mib2KNBGR4az8GiUmusBZexVBqb9YB2gm5)
+ cc5b6a454e2b614bfa18f4deb9a8e179ab985634d63b7fedfaa59573472d209b01 (mxE2iqV4jdpn4K349Gy424TvZp6MPqSXve)
+ 9b0265e0ac8c3c24fe1d79a734b3661ec2b5c0c2619bb6342356572b8235910101 (n4rGz8hkXTscUGWCwZvahrkEh6LHZVQUoa)
+ e2585af250404b7918cf6c91c6fa67f3401c0d1ae66df2fafa8fa132f4b9350f01 (moGNpEpighqc6FnkqyNVJA9xtfTiStr5YU)
+ {
+ "status": true
+ }
+```
+
+4. Fill up one of the addresses in the test framework, so we can fund `NAME_IMPORT` transactions with it:
+
+```bash
+ # NOTE: you can also do this by going to http://localhost:3001 in your Web browser
+ |blockstack-test namespace_check| $ curl -X POST -F 'addr=n4DVTuLLv5J1Yc17AoRYY1GtxDAuLGAESr' -F 'value=100000000' 'http://localhost:3001/sendfunds'
+```
+
+5. Import another name, with the child private key we just funded:
+
+```bash
+ |blockstack-test namespace_check| $ cat > /tmp/example.hello.zonefile < $ORIGIN example2.hello
+ > $TTL 3600
+ > _file URI 10 1 "file:///home/blockstack-test/example2.hello"
+ > EOF
+ |blockstack-test namespace_check| $ blockstack name_import example2.hello n3sFkNfBQPWS25G12DqDEqHRPiqHotAkEb /tmp/example.hello.zonefile aeda50305ada40aaf53f2d8921aa717f1ec71a0a3b9b4c6397b3877f6d45c46501
+ Import cost breakdown:
+ {
+ "name_import_tx_fee": {
+ "btc": 0.0003342,
+ "satoshis": 33420
+ },
+ "total_estimated_cost": {
+ "btc": 0.0003342,
+ "satoshis": 33420
+ },
+ "total_tx_fees": 33420
+ }
+ Importing name 'example2.hello' to be owned by 'n3sFkNfBQPWS25G12DqDEqHRPiqHotAkEb' with zone file hash '0649bc0b457f54c564d054ce20dc3745a0c4f0c0'
+ Proceed? (y/N) y
+ {
+ "status": true,
+ "success": true,
+ "transaction_hash": "496a6c2aaccedd98a8403c2e61ff3bdeff221a58bf0e9c362fcae981353f459f",
+ "value_hash": "0649bc0b457f54c564d054ce20dc3745a0c4f0c0"
+ }
+```
+
+6. Advance the blockchain again:
+
+```bash
+ # NOTE: you can also do this by going to http://localhost:3001 in your Web browser
+ |blockstack-test namespace_check| $ curl -X POST http://localhost:3001/nextblock
+```
+
+7. See that the names are processing:
+
+```bash
+ |blockstack-test namespace_check| $ blockstack info
+ {
+ "cli_version": "0.17.0.8",
+ "consensus_hash": "2a055beeaedcaa1365ab2671a0254a03",
+ "last_block_processed": 711,
+ "last_block_seen": 711,
+ "queues": {
+ "name_import": [
+ {
+ "confirmations": 2,
+ "name": "example.hello",
+ "tx_hash": "bd875f00f63bcb718bb22782c88c3edcbed79663f2f9152deab328c48746f103",
+ },
+ {
+ "confirmations": 1,
+ "name": "example2.hello",
+ "tx_hash": "496a6c2aaccedd98a8403c2e61ff3bdeff221a58bf0e9c362fcae981353f459f"
+ }
+ ]
+ },
+ "server_alive": true,
+ "server_host": "localhost",
+ "server_port": 16264,
+ "server_version": "0.17.0.8"
+ }
+```
+
+8. Confirm all the transactions:
+
+```bash
+ # NOTE: you can also do this by going to http://localhost:3001 in your Web browser
+ |blockstack-test namespace_check| $ for i in $(seq 1 10); do curl -X POST http://localhost:3001/nextblock
+```
+
+9. Look up name zone files to confirm they were replicated to the test framework's Atlas network:
+
+```bash
+ |blockstack-test namespace_check| $ blockstack info
+ {
+ "cli_version": "0.17.0.8",
+ "consensus_hash": "ad247c1d5ff239a65db0736951078f17",
+ "last_block_processed": 721,
+ "last_block_seen": 721,
+ "queues": {},
+ "server_alive": true,
+ "server_host": "localhost",
+ "server_port": 16264,
+ "server_version": "0.17.0.8"
+ }
+ |blockstack-test namespace_check| $ blockstack get_name_zonefile example.hello
+ $ORIGIN example.hello
+ $TTL 3600
+ _file URI 10 1 "file:///home/blockstack-test/example.hello"
+
+ |blockstack-test namespace_check| $ blockstack get_name_zonefile example2.hello
+ $ORIGIN example2.hello
+ $TTL 3600
+ _file URI 10 1 "file:///home/blockstack-test/example2.hello"
+```
+
+Now, these names are imported and once the `NAMESPACE_READY` transaction is
+sent, the name owners can proceed to issue name operations.
+
+**Warnings**
+
+* The first private key you use must be the same one you used to *create* the namespace (`$CREATOR_KEY`).
+* You may only use the 300 private keys described above to import names.
+* You must complete all `NAME_IMPORT` transactions within 52595 blocks of the `NAMESPACE_REVEAL` transaction (about 1 year).
+
+### Launching a Namespace
+
+Once you have pre-populated your namespace with all of the initial names, you
+have to make it `ready` so anyone can register a name. If you do not do this
+within 1 year of the `reveal` transaction, then your namespace and all of the
+names will disappear, and someone else will be able to register it.
+
+To make a namespace `ready`, you use the creator private key as follows:
+
+```bash
+ |blockstack-test namespace_check| $ blockstack namespace_ready hello "$CREATOR_PKEY"
+```
+
+**Warnings**
+
+* You must send the `NAMESPACE_READY` transaction within 52595 blocks (about 1 year) of the `NAMESPACE_REVEAL` transaction.
diff --git a/_core/.svn/pristine/98/989f38f3c9df34ddfdfddef592062f2423973915.svn-base b/_core/.svn/pristine/98/989f38f3c9df34ddfdfddef592062f2423973915.svn-base
new file mode 100644
index 00000000..18756f89
--- /dev/null
+++ b/_core/.svn/pristine/98/989f38f3c9df34ddfdfddef592062f2423973915.svn-base
@@ -0,0 +1,158 @@
+---
+layout: core
+permalink: /:collection/:path.html
+---
+# Choose a name
+{:.no_toc}
+
+This section explains how to choose and create a namespace, it contains the
+following sections:
+
+* TOC
+{:toc}
+
+## Intended uses for a namespace
+
+The intention is that each application can create its own BNS
+namespace for its own purposes. Applications can use namespaces for things like:
+
+* Giving users a SSO system, where each user registers their public key under a
+ username. Blockstack applications do this with names in the `.id` namespace,
+for example.
+* Providing a subscription service, where each name is a 3rd party that provides
+a service for users to subscribe to. For example, names in
+`.podcast` point to podcasts that users of the
+[DotPodcast](https://dotpodcast.co) app can subscribe to.
+* Implementing software licenses, where each name corresponds to an access key.
+ Unlike conventional access keys, access keys implemented as names
+can be sold and traded independently. The licensing fee (paid as a name
+registration) would be set by the developer and sent to a developer-controlled
+blockchain address.
+
+Names within a namespace can serve any purpose the developer wants. The ability
+to collect registration fees for 1 year after creating the namespace not only
+gives developers the incentive to get users to participate in the app, but also
+gives them a way to measure economic activity.
+
+Developers can query individual namespaces and look up names within them using
+the BNS API.
+
+## List all namespaces in existence ([reference](https://core.blockstack.org/#namespace-operations-get-all-namespaces)).
+
+```bash
+$ curl https://core.blockstack.org/v1/namespaces
+[
+ "id",
+ "helloworld",
+ "podcast"
+]
+```
+
+## List all names within a namespace ([reference](https://core.blockstack.org/#namespace-operations-get-all-namespaces))
+
+```bash
+$ curl https://core.blockstack.org/v1/namespaces/id/names?page=0
+[
+ "0.id",
+ "0000.id",
+ "000000.id",
+ "000001.id",
+ "00000111111.id",
+ "000002.id",
+ "000007.id",
+ "0011sro.id",
+ "007_007.id",
+ "00n3w5.id",
+ "00r4zr.id",
+ "00w1k1.id",
+ "0101010.id",
+ "01jack.id",
+ "06nenglish.id",
+ "08.id",
+ "0cool_f.id",
+ "0dadj1an.id",
+ "0nelove.id",
+ "0nename.id"
+...
+]
+```
+
+Each page returns a batch of 100 names.
+
+## Get the Cost to Register a Namespace ([reference](https://core.blockstack.org/#price-checks-get-namespace-price))
+
+```bash
+$ curl https://core.blockstack.org/v1/prices/namespaces/test
+{
+ "satoshis": 40000000
+}
+```
+
+If you want to register a namespace, please see the [namespace creation section]({{ site.baseurl }}/core/naming/namespace.html).
+
+## Getting the Current Consensus Hash ([reference](https://core.blockstack.org/#blockchain-operations-get-consensus-hash))
+
+```bash
+$ curl -sL https://core.blockstack.org/v1/blockchains/bitcoin/consensus
+{
+ "consensus_hash": "98adf31989bd937576aa190cc9f5fa3a"
+}
+```
+
+A recent consensus hash is required to create a `NAMESPACE_PREORDER` transaction. The reference
+BNS clients do this automatically. See the [transaction format]({{ site.baseurl }}/core/wire-format.html)
+document for details on how the consensus hash is used to construct the
+transaction.
+
+## Create a namespace
+
+ There are four steps to creating a namespace:
+
+1. **Send a `NAMESPACE_PREORDER` transaction** ([live example](https://www.blocktrail.com/BTC/tx/5f00b8e609821edd6f3369ee4ee86e03ea34b890e242236cdb66ef6c9c6a1b28)).
+This is the first step. This registers the *salted hash* of the namespace with BNS nodes, and burns the
+requisite amount of cryptocurrency. In addition, it proves to the
+BNS nodes that user has honored the BNS consensus rules by including
+a recent *consensus hash* in the transaction
+(see the section on [BNS forks](#bns-forks) for details).
+
+2. **Send a `NAMESPACE_REVEAL` transaction** ([live example](https://www.blocktrail.com/BTC/tx/ab54b1c1dd5332dc86b24ca2f88b8ca0068485edf0c322416d104c5b84133a32)).
+This is the second step. This reveals the salt and the namespace ID (pairing it with its
+`NAMESPACE_PREORDER`), it reveals how long names last in this namespace before
+they expire or must be renewed, and it sets a *price function* for the namespace
+that determines how cheap or expensive names its will be. The price function takes
+a name in this namespace as input, and outputs the amount of cryptocurrency the
+name will cost (i.e. by examining how long the name is, and whether or not it
+has any vowels or non-alphabet characters). The namespace creator
+has the option to collect name registration fees for the first year of the
+namespace's existence by setting a *namespace creator address*.
+
+3. **Seed the namespace with `NAME_IMPORT` transactions** ([live example](https://www.blocktrail.com/BTC/tx/c698ac4b4a61c90b2c93dababde867dea359f971e2efcf415c37c9a4d9c4f312)).
+Once the namespace has been revealed, the user has the option to populate it with a set of
+names. Each imported name is given both an owner and some off-chain state.
+This step is optional---namespace creators are not required to import names.
+
+4. **Send a `NAMESPACE_READY` transaction** ([live example](https://www.blocktrail.com/BTC/tx/2bf9a97e3081886f96c4def36d99a677059fafdbd6bdb6d626c0608a1e286032)).
+This is the final step of the process. It *launches* the namespace, which makes it available to the
+public. Once a namespace is ready, anyone can register a name in it if they
+pay the appropriate amount of cryptocurrency (according to the price funtion
+revealed in step 2).
+
+The reason for the `NAMESPACE_PREORDER/NAMESPACE_REVEAL` pairing is to prevent
+frontrunning. The BNS consensus rules require a `NAMESPACE_REVEAL` to be
+paired with a previous `NAMESPACE_PREORDER` sent within the past 24 hours.
+If it did not do this, then a malicious actor could watch the blockchain network
+and race a victim to claim a namespace.
+
+Namespaces are created on a first-come first-serve basis. If two people try to
+create the same namespace, the one that successfully confirms both the
+`NAMESPACE_PREORDER` and `NAMESPACE_REVEAL` wins. The fee burned in the
+`NAMESPACE_PREORDER` is spent either way.
+
+Once the user issues the `NAMESPACE_PREORDER` and `NAMESPACE_REVEAL`, they have
+1 year before they must send the `NAMESPACE_READY` transaction. If they do not
+do this, then the namespace they created disappears (along with all the names
+they imported).
+
+Developers wanting to create their own namespaces should read the [namespace creation section]({{ site.baseurl }}/core/naming/namespace.html) document. It is highly recommended that
+developers request individual support before creating their own space, given the large amount of
+cryptocurrency at stake.
diff --git a/_core/.svn/pristine/9a/9aad8a1f494fee6e8feddda639efa01be5abfd5b.svn-base b/_core/.svn/pristine/9a/9aad8a1f494fee6e8feddda639efa01be5abfd5b.svn-base
new file mode 100644
index 00000000..5282d816
--- /dev/null
+++ b/_core/.svn/pristine/9a/9aad8a1f494fee6e8feddda639efa01be5abfd5b.svn-base
@@ -0,0 +1,119 @@
+---
+layout: core
+permalink: /:collection/:path.html
+---
+# Naming system feature comparison
+{:.no_toc}
+
+BNS is not the only naming system in wide-spread use, nor is it the only
+decentralized naming system that implements human-readable, globally-unique, and
+strongly-owned names. This page describes some other naming systems in
+comparison to Blockstack:
+
+* TOC
+{:toc}
+
+
+## Blockstack vs DNS
+
+Blockstack and DNS both implement naming systems, but in fundamentally
+different ways. Blockstack *can be used* for resolving host names to IP
+addresses, but this is not its default use-case. The [Blockstack Naming
+Service]({{ site.baseurl }}/core/naming/introduction.html) (BNS) instead behaves
+more like a decentralized
+[LDAP](https://en.wikipedia.org/wiki/Lightweight_Directory_Access_Protocol) system for
+resolving user names to user data.
+
+While DNS and BNS handle different problems, they share some terminology and
+serialization formats. However, it is important to recognize that this is the
+*only* thing they have in common---BNS has fundamentally different semantics
+than DNS:
+
+* **Zone files**: Blockstack stores a DNS zone file for each name. However,
+the semantics of a BNS zone file are nothing like the semantics of a DNS zone
+file---the only thing they have in common is their format.
+A "standard" Blockstack zone files only have `URI` and `TXT` resource records
+that point to the user's application data. Moreover, a Blockstack ID has a
+*history* of zone files, and historic zone files can alter the way in which a
+Blockstack ID gets resolved (DNS has no such concept). It is conceivable that an advanced
+user could add `A` and `AAAA` records to their Blockstack ID's zone file,
+but these are not honored by any Blockstack software at this time.
+
+* **Subdomains**: Blockstack has the concept of a subdomain, but it is
+ semantically very different from a DNS subdomain. In Blockstack, a subdomain
+is a Blockstack ID whose state and transaction history are anchored to the
+blockchain, but stored within an on-chain Blockstack ID's zone file history.
+Unlike DNS subdomains, a BNS subdomain has
+its own owner and is a first-class BNS name---all subdomains are resolvable,
+and only the subdomain's owner can update the subdomain's records. The only thing BNS subdomains and DNS
+subdomains have in common is the name format (e.g. `foo.bar.baz` is a subdomain
+of `bar.baz` in both DNS and BNS).
+
+More details can be found in the [Blockstack vs
+DNS]({{ site.baseurl }}/core/naming/comparison.html) document. A feature
+comparison can be found at the end of the [Blockstack Naming
+Service]({{ site.baseurl }}/core/naming/introduction.html) document.
+
+## Blockstack vs Namecoin
+
+Namecoin also implements a decentralized naming service on top of a blockchain,
+just like BNS. In fact, early versions of Blockstack were built on Namecoin.
+However, [it was discovered](https://www.usenix.org/node/196209) that Namecoin's
+merged mining with Bitcoin regularly placed it under the *de facto* control of a single
+miner. This prompted a re-architecting of the system to be *portable* across
+blockchains, so that if Blockstack's underlying blockchain (currently Bitcoin)
+ever became insecure, the system could migrate to a more secure blockchain.
+
+A feature comparison can be found at the end of the [Blockstack Naming
+Service]({{ site.baseurl }}/core/naming/introduction.html) document.
+
+## Blockstack vs ENS
+
+ENS also implements a decentralized naming system on top of a blockchain, but as
+a smart contract on Ethereum. Like BNS, ENS is geared towards resolving names
+to off-chain state (ENS names resolve to a hash, for example). Moreover, ENS is
+geared towards providing programmatic control over names with Turing-complete
+on-chain resolvers.
+
+BNS has a fundamentally different relationship with blockchains than ENS.
+WHereas ENS tries to use on-chain logic as much as possible, BNS
+tries to use the blockchain as little as possible. BNS only uses it to store a
+database log for name operations (which are interpreted with an off-chain BNS
+node like Blockstack Core). BNS name state and BNS subdomains reside entirely
+off-chain in the Atlas network. This has allowed BNS to migrate from blockchain
+to blockchain in order to survive individual blockchain failures, and this has
+allowed BNS developers to upgrade its consensus rules without having to get the
+blockchain's permission (see the [virtualchain
+paper](https://blockstack.org/virtualchain.pdf) for details).
+
+## Summary feature comparison
+
+
+The following feature table provides a quick summary how BNS differs from other naming systems
+
+| Feature | BNS | [ENS](https://ens.domains/) | DNS | [Namecoin](https://namecoin.org/) |
+|----------------------------|-----|-----|-----|----------|
+| Globally unique names | X | X | X | X |
+| Human-readable names | X | X | X | X |
+| Strongly-owned names | X | X | | X |
+| Names are enumerable | X | | | X |
+| Registration times | 1-2 hours | ~1 week | ~1 day | 1-2 hours |
+| Subdomain registration times | 1 hour (instant with [#750](https://github.com/blockstack/blockstack-core/issues/750)) | varies | instant | ~1 hour |
+| Anyone can make a TLD/namespace | X | [1] | | [1] |
+| TLD/Namespace owners get registration fees | X | | X | |
+| TLD/Namespace can be seeded with initial names | X | | X | |
+| Portable across blockchains | X | | N/A | |
+| Off-chain names | X | | N/A | |
+| Off-chain name state | X | X | N/A | |
+| Name provenance | X | X | | X |
+| [DID](http://identity.foundation) support | X | | | |
+| Turing-complete namespace rules | | X | X | |
+| Miners are rewarded for participating | [1] | | N/A | X |
+
+[1] Requires support in higher-level applications. These systems are not aware
+of the existence of namespaces/TLDs at the protocol level.
+
+[2] Blockstack Core destroys the underlying blockchain token to pay for
+registration fees when there is no pay-to-namespace-creator address set in the
+name's namespace. This has the effect of making the blockchain miners' holdings
+slightly more valuable.
diff --git a/_core/.svn/pristine/9b/9bfaf05ef17f1ce4201fa0bd80dba18f8648bb5e.svn-base b/_core/.svn/pristine/9b/9bfaf05ef17f1ce4201fa0bd80dba18f8648bb5e.svn-base
new file mode 100644
index 00000000..12858de4
--- /dev/null
+++ b/_core/.svn/pristine/9b/9bfaf05ef17f1ce4201fa0bd80dba18f8648bb5e.svn-base
@@ -0,0 +1,110 @@
+---
+layout: core
+permalink: /:collection/:path.html
+---
+# Register a name
+{:.no_toc}
+
+This section explains registering BNS names and provides instructions for methods
+you can use to understandt the cost of namespace registration.
+
+* TOC
+{:toc}
+
+## Understand registration
+
+Registering a BNS name costs cryptocurrency. This cost comes from two sources:
+
+* **Transaction fees:** These are the fees imposed by the cost of storing the
+ transaction data to the blockchain itself. They are independent of BNS, since
+all of the blockchain's users are competing to have their transactions included
+in the next block. The blockchain's miners receive the transaction fee.
+
+* **Registration fees:** Each BNS namespace imposes an *additional* fee on how
+ much a name costs. The registration fee is sent to the namespace creator
+during the first year that a namespace exists, and is sent to a burn address
+afterwards. The registration fee is different for each name and is
+determined by the namespace itself, but can be queried in advance by the user.
+
+Registering a name takes two transactions. They are:
+
+* **`NAME_PREORDER` transaction**: This is the first transaction to be sent.
+ It tells all BNS nodes the *salted hash* of the BNS name, and it pays the
+registration fee to the namespace owner's designated address (or the burn
+address). In addition, it proves to the BNS nodes that the client knows about
+the current state of the system by including a recent *consensus hash*
+in the transaction (see the section on [BNS forks](#bns-forks) for details).
+
+* **`NAME_REGISTRATION` transaction**: This is the second transaction to be
+ sent. It reveals the salt and the name to all BNS nodes, and assigns the name
+an initial public key hash and zone file hash
+
+The reason this process takes two transactions is to prevent front-running.
+The BNS consensus rules stipulate that a name can only be registered if its
+matching preorder transaction was sent in the last 24 hours. Because a name
+must be preordered before it is registered, someone watching the blockchain's
+peer network cannot race a victim to claim the name they were trying to
+register (i.e. the attacker would have needed to send a `NAME_PREORDER`
+transaction first, and would have had to have sent it no more than 24 hours
+ago).
+
+Registering a name on top of the Bitcoin blockchain takes 1-2 hours. This is
+because you need to wait for the `NAME_PREORDER` transaction to be sufficiently
+confirmed before sending the `NAME_REGISTRATION` transaction. The BNS nodes
+only register the name once both transactions have at least 6 confirmations
+(which itself usually takes about an hour).
+
+Names are registered on a first-come first-serve basis.
+If two different people try to register the same name at the same time, the
+person who completes the two-step process *earliest* will receive the name. The
+other person's `NAME_REGISTRATION` transaction will be ignored, since it will
+not be considered valid at this point. The registration fee paid by the
+`NAME_PREORDER` will be lost. However, this situation is rare in practice---
+as of early 2018, we only know of one confirmed instance in the system's 3+ years
+of operation.
+
+Fully-qualified names can be between 3 and 37 characters long, and consist of
+the characters `a-z`, `0-9`, `+`, `-`, `_`, and `.`. This is to prevent
+[homograph attacks](https://en.wikipedia.org/wiki/IDN_homograph_attack).
+`NAME_REGISTRATION` transactions that do not conform to this requirement will be
+ignored.
+
+## Getting a Name's Registration Fee ([reference](https://core.blockstack.org/#price-checks-get-name-price))
+
+```bash
+$ curl -sL https://core.blockstack.org/v1/prices/names/helloworld.id | jq -r ".name_price"
+{
+ "btc": 2.5e-05,
+ "satoshis": 2500
+}
+```
+
+Note the use of `jq -r` to select the `"name_price"` field. This API
+endpoint may return other ancilliary data regarding transaction fee estimation,
+but this is the only field guaranteed by this specification to be present.
+
+## Getting the Current Consensus Hash ([reference](https://core.blockstack.org/#blockchain-operations-get-consensus-hash))
+
+```bash
+$ curl -sL https://core.blockstack.org/v1/blockchains/bitcoin/consensus
+{
+ "consensus_hash": "98adf31989bd937576aa190cc9f5fa3a"
+}
+```
+
+The consensus hash must be included in the `NAME_PREORDER` transaction. The BNS
+clients do this automatically. See the [transaction format
+document]({{ site.baseurl }}/core/wire-format.html) for details as to how to include this in the
+transaction.
+
+## Registering a Name
+
+Registration happens through a BNS client, such as the [Blockstack
+Browser](https://github.com/blockstack/blockstack-browser) or
+[blockstack.js](https://github.com/blockstack/blockstack.js).
+The reference BNS clients manage a local Bitcoin wallet, calculate transaction fees
+dynamically and automatically, and broadcast both the `NAME_PREORDER` and
+`NAME_REGISTRATION` transactions at the right times.
+
+If you want to make your own registration client, you should see the
+[transaction format]({{ site.baseurl }}/core/wire-format.html) document.
diff --git a/_core/.svn/pristine/9e/9edc569e2fdc45751cf8a4998e6976be26356039.svn-base b/_core/.svn/pristine/9e/9edc569e2fdc45751cf8a4998e6976be26356039.svn-base
new file mode 100644
index 00000000..3e9df493
--- /dev/null
+++ b/_core/.svn/pristine/9e/9edc569e2fdc45751cf8a4998e6976be26356039.svn-base
@@ -0,0 +1,184 @@
+---
+layout: core
+permalink: /:collection/:path.html
+---
+# How Atlas Works
+{:.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.
+
+This section contains the following sections:
+
+* TOC
+{:toc}
+
+## Peer Selection
+
+Atlas peers self-organize into an unstructured peer-to-peer network.
+The Atlas peer network is a [random K-regular
+graph](https://en.wikipedia.org/wiki/Random_regular_graph). Each node maintains
+*K* neighbors chosen at random from the set of Atlas peers.
+
+Atlas nodes select peers by carrying out an unbiased random walk of the peer
+graph. When "visiting" a node *N*, it will ask for *N*'s neighbors and then
+"step" to one of them with a probability dependent on *N*'s out-degree and the
+neighbor's in-degree.
+
+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:
+
+* If the neighbors of the visited node *N* 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.
+
+* The transition probability from *N* to a live neighbor is *NOT* `min(1,
+degree(neighbor)/degree(N))` like it is in the vanilla MH algorithm. Instead,
+the transition probability discourages backtracking to the previous neighbor *N_prev*,
+but in a way that still guarantees that the sampling will remain unbiased.
+
+* 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.
+
+* A new neighbor is only selected if it belongs to the same [BNS
+ fork-set]({{site.baseurl}}/core/naming/introduction.html#bns-forks) (i.e. it reports
+as having a recent valid consensus hash).
+
+The algorithm was adapted from the work from [Lee, Xu, and
+Eun](https://arxiv.org/pdf/1204.4140.pdf) in the proceedings of
+ACM SIGMETRICS 2012.
+
+## Comparison to DHTs
+
+The reason Atlas uses an unstructured random peer network
+instead of a [distributed hash table](https://en.wikipedia.org/wiki/Distributed_hash_table)
+(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.
+
+### Chunk Censorship
+
+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 *fundamental* 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.
+
+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 *independent* of the content and *randomized* 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).
+
+### Neighbor Censorship
+
+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).
+
+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.
+
+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.
+
+## Chunk Propagation
+
+Atlas nodes maintain an *inventory* 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.
+
+Atlas peers keep track of which chunks are present and which are absent. They
+each construct an *inventory vector* of chunks *V* such that *V[i]* is set to 1
+if the node has the chunk whose hash is in the *i*th position in the chunk
+sequence (and set to 0 if it is absent).
+
+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.
+
+```
+ 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.
+```
+
+## Querying Chunk Inventories
+
+Developers can query a node's inventory vector as follows:
+
+```python
+>>> import blockstack
+>>> result = blockstack.lib.client.get_zonefile_inventory("https://node.blockstack.org:6263", 0, 524288)
+>>> print len(result['inv'])
+11278
+>>>
+```
+
+The variable `result['inv']` here is a big-endian bit vector, where the *i*th
+bit is set to 1 if the *i*th chunk in the chunk sequence is present. The bit at
+`i=0` (the earliest chunk) refers to the leftmost bit.
+
+A sample program that inspects a set of Atlas nodes' inventory vectors and determines
+which ones are missing which chunks can be found
+[here](https://github.com/blockstack/atlas/blob/master/atlas/atlas-test).
diff --git a/_core/.svn/pristine/a1/a18bdd69060f6b4019400c15fa85fd7f93b7574e.svn-base b/_core/.svn/pristine/a1/a18bdd69060f6b4019400c15fa85fd7f93b7574e.svn-base
new file mode 100644
index 00000000..4f097de3
--- /dev/null
+++ b/_core/.svn/pristine/a1/a18bdd69060f6b4019400c15fa85fd7f93b7574e.svn-base
@@ -0,0 +1,126 @@
+---
+layout: core
+permalink: /:collection/:path.html
+---
+# Overview of the Atlas network
+{:.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 **permanently store** chunks of data that are
+**replicated across every peer.** As long as at least one Atlas peer is online,
+all chunks are available to clients.
+
+This document is aimed at developers and technical users. The following
+concepts are discussed:
+
+* TOC
+{:toc}
+
+The reader of this document is expected to be familiar with the [Blockstack Naming Service]({{site.baseurl}}/core/naming/introduction.html)(BNS), as well as Blockstack's
+storage system [Gaia](https://github.com/blockstack/gaia). We advise the reader
+to familiarize themselves with both systems before approaching this document.
+
+## Architecture
+
+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:
+
+* Storing a name's routing information for its owners' [Gaia](https://github.com/blockstack/gaia)
+datastores.
+* Storing BNS subdomain transactions and associated state.
+
+Atlas is a middleware system in Blockstack. Most developers do not
+interact with it directly. BNS clients like the
+[Blockstack Browser](https://github.com/blockstack/blockstack-browser)
+automatically generate zone files for the names they register, and automatically
+propagate them to the Atlas network. BNS API endpoints, including our
+[public endpoint](https://core.blockstack.org) and the
+[blockstack.js](https://github.com/blockstack/blockstack.js) library,
+will automatically fetch zone files from Atlas when they need to look
+up data in Gaia (such as profiles and app data).
+
+```
+ +--------------+ +---------------+ +----------------+
+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.
+```
+
+Nevertheless, Atlas is a general-purpose content-addressed storage
+system that advanced developers can use to **host data in an immutable
+and durable manner.** Beyond its default use-case in Blockstack,
+Atlas is ideal for tasks like:
+
+* Announcing PGP public keys under a human-readable name
+* Storing package hashes for a software release
+* Securely deploying shell scripts to remote VMs
+* Binding human-readable names to Tor .onion addresses
+ ([example](https://github.com/blockstack-packages/blockstack-tor))
+
+## Motivation
+
+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.
+
+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
+*preserves the security properties of having written that state to the
+blockchain*. Instead of storing 20 bytes of data on the blockchain, a BNS name
+owner would store the *cryptograhpic hash* of its state, and then store the actual state
+Atlas. This decouples the name's state size from the blockchain.
+
+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.
+
+## Feature Comparison
+
+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.
+
+| **Features** | Atlas | BitTorrent | [DAT](https://datproject.org/) | [IPFS](https://ipfs.io) | [Swarm](https://github.com/ethersphere/swarm) |
+|-----------------------------|-------|------------|--------------------------------|-------------------------|-----------------------------------------------|
+| Each peer stores all chunks | X | X | | | |
+| Replicas are permanent [1] | X | X | X | | |
+| Replicas are free | | X | X | X | |
+| Sybil-resistant chunk discovery | X | X | | | X |
+| Sybil-resistant peer discovery | X | | | | |
+| Fixed chunk size | X | | X | X | X |
+
+[1] Here, "permanent" means that once a peer has data, they will never evict it
+as part of the protocol.
diff --git a/_core/.svn/pristine/a3/a3d4f2535f389317b9715aad71c1a4602fb32527.svn-base b/_core/.svn/pristine/a3/a3d4f2535f389317b9715aad71c1a4602fb32527.svn-base
new file mode 100644
index 00000000..a9c3abf6
--- /dev/null
+++ b/_core/.svn/pristine/a3/a3d4f2535f389317b9715aad71c1a4602fb32527.svn-base
@@ -0,0 +1,5 @@
+# About this `docs` directory
+
+The contents of this directory acts as source for material for
+[docs.blockstack.org](https://docs.blockstack.org/), a searchable documentation
+site for all things Blockstack.
diff --git a/_core/.svn/pristine/a5/a576c2f876a3fcd9da87fa112d434e0371441da9.svn-base b/_core/.svn/pristine/a5/a576c2f876a3fcd9da87fa112d434e0371441da9.svn-base
new file mode 100644
index 00000000..9871c12c
--- /dev/null
+++ b/_core/.svn/pristine/a5/a576c2f876a3fcd9da87fa112d434e0371441da9.svn-base
@@ -0,0 +1,4 @@
+# Legacy, Deprecated, or No longer Useful Documentation
+
+Documents here are out-of-date but preserved for posterity. Do not rely on
+them.
diff --git a/_core/.svn/pristine/a8/a8dfc560ed642fbda739d9e8e0ba25fb8e707415.svn-base b/_core/.svn/pristine/a8/a8dfc560ed642fbda739d9e8e0ba25fb8e707415.svn-base
new file mode 100644
index 00000000..c04e1613
--- /dev/null
+++ b/_core/.svn/pristine/a8/a8dfc560ed642fbda739d9e8e0ba25fb8e707415.svn-base
@@ -0,0 +1,185 @@
+---
+layout: core
+permalink: /:collection/:path.html
+---
+# Blockstack Technical FAQ
+{:.no_toc}
+* TOC
+{:toc}
+
+
+
+This document lists frequently-asked questions and answers to technical
+questions about Blockstack.
+
+If you are new to Blockstack, you should read the
+[non-technical FAQ](https://blockstack.org/faq) first.
+
+If you have a technical question that gets frequently asked on the
+[forum](https://forum.blockstack.org) or [Slack](https://blockstack.slack.com),
+feel free to send a pull-request with the question and answer.
+
+## Who should build on Blockstack?
+
+Everyone! But more seriously, if you are building an application in JavaScript
+that requires sign-in and storage you should look at using Blockstack. The APIs
+we provide are not only decentralized (No dependency on Google, Facebook, or
+other OAuth provider) but easier to use than traditional OAuth. Also you no
+longer have to maintain and secure databases with all your user information.
+That data is stored securely with the people who created it.
+
+## What is a "serverless" app?
+
+The application itself should not run application-specific functionality on a server. All of its functionality should run on end-points. However, the application may use non-app-specific servers with the caveat that they must not be part of the trusted computing base. This is the case with storage systems like Amazon S3 and Dropbox, for example, because Blockstack's data is signed and verified end-to-end (so the storage systems are not trusted to serve data). Serverless can also mean applications where some amount of server-side logic is still written by the application developer but unlike traditional architectures is run in stateless compute containers that are event-triggered, ephemeral (may only last for one invocation)
+
+
+## How are Blockstack domains different from normal DNS domains?
+
+Blockstack domains are not registered on the traditional DNS run by an organized called ICANN. Instead they're registered on a blockchain in a fully decentralized way. This means that Blockstack domains are truly owned by their owners and cannot be taken away. All Blockstack domains have public keys by default (public keys are required to own the domains), unlike the traditional DNS where a small fraction of domains get the (optional) public key certificates.
+
+## What is a virtual chain?
+
+Blockstack is designed around a "virtual chain" concept, where nodes only need to reach consensus on the shared "virtual chain" they're interested in. Virtual chains do not interact with one another, and a single blockchain can host many virtual chains. These virtual chains can live in any blockchain for which there exists a driver, and virtual chain clients only need to execute their virtual chain transactions (i.e. Blockstack only processes Blockstack virtual chain transactions).
+
+## What is Blockstack Core and who is working on it?
+
+Blockstack Core is the reference implementation of the Blockstack protocol described in our white paper. It consists of a couple of parts:
+
+- Virtualchain implementation: This is a python library that parses the underlying blockchain (Bitcoin) and builds the state of the Blockstack DNS.
+- Blockstack Core: Uses the Virtualchain to build the DNS state and comes to a consensus on that state in a peer network (Atlas).
+- Blockstack API: Indexes the data stored by Blockstack Core and makes it available in a performant way to applications.
+
+The project is open-source and anyone can contribute! The major contributors are mostly employees of Blockstack PBC. You can see the full list of contributors here: https://github.com/blockstack/blockstack-core/graphs/contributors
+
+
+## How is Blockstack different from Ethereum for building decentralized apps?
+
+You can think of Ethereum as a "heavy" blockchain that does everything for you. All the complexity is handled on-chain, computations are run there, and all scalability and security concerns need to be handled at the blockchain level. It amounts to a "mainframe" that runs all the applications in the ecosystem.
+
+Blockstack puts minimal logic into a blockchain and handles scalability outside of the blockchain by re-using existing internet infrastructure. Our architectural design mirrors how computing has developed; moving from mainframes to smaller networked entities.
+
+Read more about the differences between Blockstack and Ethereum dapps in the following forum post: https://forum.blockstack.org/t/what-is-the-difference-between-blockstack-and-ethereum/781/2
+
+## Can Blockstack only run on Bitcoin?
+
+The model we're currently exploring is where Blockstack can process multiple blockchains to construct the global state where each namespace is tied to a single blockchain. Meaning that say the .id namespace is defined to run on Bitcoin and a .eth namespace is defined to run on Ethereum. Blockstack can process transactions from both blockchains and update the state of namespaces, but the consistency of any given namespace depends only on the underlying blockchain it was defined on.
+
+## Does Blockstack use a DHT (Distributed Hash Table)?
+
+It does not, as of November 2016. It uses a much more reliable system called the Atlas Network. Details here: https://blog.blockstack.org/blockstack-core-v0-14-0-release-aad748f46d#.30gzlthdw
+
+## Can the Blockstack network fork?
+
+Yes, the Blockstack network can fork if the underlying blockchain encounters a deep fork. In this case, blockstack nodes on either side of the fork will diverge from one another.
+
+We have yet to encounter a deep fork. If this does happen, then Blockstack will use the virtualchain state on the majority fork once the fork resolves.
+
+We also hard fork the network once a year to make protocol breaking changes and upgrade the network. The last one of these happened on block `488500` on the bitcoin blockchain. There are more details about the fork in this forum post: https://forum.blockstack.org/t/blockstack-annual-hard-fork-2017/1618
+
+## How is the Blockstack network upgraded over time? What parties need to agree on an upgrade?
+
+We're working on an on-chain voting strategy similar to how mining works, where anyone can cast a vote proportional to the amount of Bitcoin burned. Similar to how Bitcoin upgrades, a new feature will activate if a certain threshold (e.g. 80%) of votes consistently request its adoption over a given time interval (e.g. a couple weeks).
+
+Until then, we will publicly announce the availability of new software, with the promise that each release will bring highly-desired features to make upgrading worth the users' whiles.
+
+## Who gets the registration fees for name registrations?
+
+With the current design, names are purchased by paying tribute with Bitcoin mining fees.
+
+
+## Where are the current core developers based? What are the requirements for being a core developer?
+
+Most of the core developers work in NYC and Hong Kong. Developers who've contributed to the [core open-source software](https://github.com/blockstack/blockstack-core) over a long enough time period, by default, get included in the list of core developers. There is no formal process for being part of this informal list. Core developers, generally, have the ability to write high-quality code, understand distributed systems and applied crypto, and share a vision of building a truly decentralized internet and are dedicated to that cause.
+
+## I heard some companies working on Blockstack have raised venture capital, how does that impact the project?
+
+Blockstack, like Linux, is an open-source project with a GPLv3 license for the core technology. Just like different companies build apps and services on top of Linux and have different individual business models, there are companies who're building apps & services for Blockstack on top of the core open-source technology and these companies have various business models and funding sources respectively. Having more venture-backed companies join the ecosystem for a decentralized internet is a good thing for everyone participating in the ecosystem including users and developers.
+
+## Where is my data stored and how do I control who access it?
+
+You control where your data is stored (you could run your own server, or use your own cloud storage - Dropbox, Amazon S3, and keep backups across all). You then use those places as locations pointed to by the URLs in your Blockstack ID's zone file.
+
+## Why should I trust the information, like name ownership or public key mappings, read from Blockstack?
+
+Blockstack records are extremely hard to tamper with. This is because the bindings for name ownership (names on Blockstack are owned by public keys) are announced in a proof-of-work blockchain (Bitcoin) and to change these binding an attacker will need to come up with a blockchain with more proof-of-work than the current Bitcoin blockchain but with a different history. Bitcoin's [current hash rate](https://blockchain.info/charts/hash-rate) makes this task almost impossible for non-state actors.
+
+## Can anyone register a TLD?
+
+Yes, anyone can register a TLD. If a TLD has not been registered already and you're willing to pay the registration fee for it, you can go ahead and register that TLD. There is no centralized party that can stop you from registering a TLD.
+
+
+## What programming language can I use to build these apps?
+
+To make apps that run in the web browser using Blockstack, you can use JavaScript and any of the same web frameworks or libraries you use today such as React, AngularJs, Vue.js or jQuery. The Blockstack Core is implementated in Python, but you can use any language you like for native apps as long as you are able to consume a JSON REST API.
+
+
+## Do I need to run a full Blockstack node to use Blockstack?
+
+tl;dr: You don't, but its very easy to.
+
+To reduce the overhead involved in getting started we maintain a fleet of Blockstack Core nodes that your Blockstack applications connect to by default. If you want to run your own we provide detailed instructions on our [install page](https://blockstack.org/install). It only takes about 5-10 minutes to spin up your full node!
+
+## What is the capacity per block for registrations using Blockstack?
+
+Initial registrations can be done at an order of hundreds per block and once an identity is registered you can do “unlimited” updates to the data because that is off-chain. We’re also working on a more scalable solution where a very large number of identities can be registered but that’s not live yet and is in the pipeline as a rough benchmark. in summer 2015, Blockstack did 30,000+ identity registrations in a matter of few days live on the blockchain and Blockstack was actually throttling its servers and not taking up more than 100-200 transactions per block. It could’ve easily taken up more transactions without impacting the network.
+
+## What language is the Blockstack software written in?
+
+Python 2 and Node.js
+
+## What incentives are there to run a Blockstack node?
+
+Running a Blockstack node keeps you secure by ensuring that your app gets the right names and public keys. It's not expensive; it takes as much resources as a Chrome tab.
+
+## Can Blockstack apps scale, given that Blockstack uses blockchains which don't scale that well?
+
+Yes. Blockstack only uses the blockchain for name registration. Everything else happens off-chain, so apps work just as fast as they do on the Web.
+
+## What if the current companies and developers working on Blockstack disappear, would the network keep running?
+
+Yes, the Blockstack network will keep running. All of Blockstack's code is open-source and anyone can deploy Blockstack nodes or maintain the code. Further, Blockstack nodes don't need to coordinate with each other to function. Any node that a user deploys can function correctly independently.
+
+
+## Where does Blockstack keep my app data?
+
+As a Blockstack user, you can choose exactly where your data gets stored.
+Blockstack uses a decentralized storage system called
+[Gaia](https://github.com/blockstack/gaia) to host your data. Gaia is different
+from other storage systems because it lets you securely host your data wherever you want---in cloud
+storage providers, on your personal server, or in another decentralized storage
+system like BitTorrent or IPFS.
+
+When you register, you are given a default Gaia hub that replicates your
+data to a bucket in Microsoft Azure. However, you can configure and
+deploy your own Gaia hub and have Blockstack store your data there instead.
+
+The [Blockstack Naming Service]({{ site.baseurl }}/core/naming/introduction.html) and the [Atlas network]({{ site.baseurl }}/core/atlas/overview.html) work together to help other users discover your
+app-specific public data, given your Blockstack ID.
+
+## What is a Blockstack Subdomain?
+
+This is also a Blockstack ID, and can be used for all the things a Blockstack ID
+can be used for. The only difference is that they have the format `foo.bar.baz`
+instead of `bar.baz`. For example,
+[jude.personal.id](https://core.blockstack.org/v1/users/jude.personal.id) is a
+Blockstack ID, and is a subdomain of `personal.id`.
+
+Subdomains are first-class Blockstack IDs---they can be used for all the same
+things that an on-chain Blockstack ID can be used for, and they have all of
+the same safety properties. They are globally unique, they are strongly owned
+by a private key, and they are human-readable.
+
+Subdomains are considerably cheaper than Blockstack IDs, since hundreds of them
+can be registered with a single transaction. The [BNS
+documentation]({{ site.baseurl }}/core/naming/introduction.html) describes them in detail.
+
+Subdomains provide a fast, inexpensive way to onboard many users at once.
+
+## Can I get a Blockstack ID without spending Bitcoin?
+
+Blockstack subdomains can be obtained without spending Bitcoin
+by asking a subdomain registrar to create one for you.
+
+## Is there a Blockstack name explorer?
+
+Yes! It's at https://explorer.blockstack.org
diff --git a/_core/.svn/pristine/b2/b246f4d44a8232ae569139be54661438496e1012.svn-base b/_core/.svn/pristine/b2/b246f4d44a8232ae569139be54661438496e1012.svn-base
new file mode 100644
index 00000000..c977e962
--- /dev/null
+++ b/_core/.svn/pristine/b2/b246f4d44a8232ae569139be54661438496e1012.svn-base
@@ -0,0 +1,499 @@
+---
+layout: core
+permalink: /:collection/:path.html
+---
+# Bitcoin wire format
+{:.no_toc}
+
+This page is for organizations who want to be able to create and send name operation transactions to the blockchain(s) Blockstack supports.
+It describes the transaction formats for the Bitcoin blockchain.
+
+* TOC
+{:toc}
+
+## Transaction format
+
+Each Bitcoin transaction for Blockstack contains signatures from two sets of keys: the name owner, and the payer. The owner `scriptSig` and `scriptPubKey` fields are generated from the key(s) that own the given name. The payer `scriptSig` and `scriptPubKey` fields are used to *subsidize* the operation. The owner keys do not pay for any operations; the owner keys only control the minimum amount of BTC required to make the transaction standard. The payer keys only pay for the transaction's fees, and (when required) they pay the name fee.
+
+This construction is meant to allow the payer to be wholly separate from the owner. The principal that owns the name can fund their own transactions, or they can create a signed transaction that carries out the desired operation and request some other principal (e.g. a parent organization) to actually pay for and broadcast the transaction.
+
+The general transaction layout is as follows:
+
+| **Inputs** | **Outputs** |
+| ------------------------ | ----------------------- |
+| Owner scriptSig (1) | `OP_RETURN ` (2) |
+| Payment scriptSig | Owner scriptPubKey (3) |
+| Payment scriptSig... (4) |
+| ... (4) | ... (5) |
+
+(1) The owner `scriptSig` is *always* the first input.
+(2) The `OP_RETURN` script that describes the name operation is *always* the first output.
+(3) The owner `scriptPubKey` is *always* the second output.
+(4) The payer can use as many payment inputs as (s)he likes.
+(5) At most one output will be the "change" `scriptPubKey` for the payer.
+Different operations require different outputs.
+
+## Payload Format
+
+Each Blockstack transaction in Bitcoin describes the name operation within an `OP_RETURN` output. It encodes name ownership, name fees, and payments as `scriptPubKey` outputs. The specific operations are described below.
+
+Each `OP_RETURN` payload *always* starts with the two-byte string `id` (called the "magic" bytes in this document), followed by a one-byte `op` that describes the operation.
+
+### NAME_PREORDER
+
+Op: `?`
+
+Description: This transaction commits to the *hash* of a name. It is the first
+transaction of two transactions that must be sent to register a name in BNS.
+
+Example: [6730ae09574d5935ffabe3dd63a9341ea54fafae62fde36c27738e9ee9c4e889](https://www.blocktrail.com/BTC/tx/6730ae09574d5935ffabe3dd63a9341ea54fafae62fde36c27738e9ee9c4e889)
+
+`OP_RETURN` wire format:
+```
+ 0 2 3 23 39
+ |-----|--|--------------------------------------------------|--------------|
+ magic op hash_name(name.ns_id,script_pubkey,register_addr) consensus hash
+```
+
+Inputs:
+* Payment `scriptSig`'s
+
+Outputs:
+* `OP_RETURN` payload
+* Payment `scriptPubkey` script for change
+* `p2pkh` `scriptPubkey` to the burn address (0x00000000000000000000000000000000000000)
+
+Notes:
+* `register_addr` is a base58check-encoded `ripemd160(sha256(pubkey))` (i.e. an address). This address **must not** have been used before in the underlying blockchain.
+* `script_pubkey` is either a `p2pkh` or `p2sh` compiled Bitcoin script for the payer's address.
+
+### NAME_REGISTRATION
+
+Op: `:`
+
+Description: This transaction reveals the name whose hash was announced by a
+previous `NAME_PREORDER`. It is the second of two transactions that must be
+sent to register a name in BNS.
+
+Example: [55b8b42fc3e3d23cbc0f07d38edae6a451dfc512b770fd7903725f9e465b2925](https://www.blocktrail.com/BTC/tx/55b8b42fc3e3d23cbc0f07d38edae6a451dfc512b770fd7903725f9e465b2925)
+
+`OP_RETURN` wire format (2 variations allowed):
+
+Variation 1:
+```
+ 0 2 3 39
+ |----|--|-----------------------------|
+ magic op name.ns_id (37 bytes)
+```
+
+Variation 2:
+```
+ 0 2 3 39 59
+ |----|--|----------------------------------|-------------------|
+ magic op name.ns_id (37 bytes, 0-padded) value
+```
+
+Inputs:
+* Payer `scriptSig`'s
+
+Outputs:
+* `OP_RETURN` payload
+* `scriptPubkey` for the owner's address
+* `scriptPubkey` for the payer's change
+
+Notes:
+
+* Variation 1 simply registers the name. Variation 2 will register the name and
+set a name value simultaneously. This is used in practice to set a zone file
+hash for a name without the extra `NAME_UPDATE` transaction.
+* Both variations are supported. Variation 1 was designed for the time when
+ Bitcoin only supported 40-byte `OP_RETURN` outputs.
+
+### NAME_RENEWAL
+
+Op: `:`
+
+Description: This transaction renews a name in BNS. The name must still be
+registered and not expired, and owned by the transaction sender.
+
+Example: [e543211b18e5d29fd3de7c0242cb017115f6a22ad5c6d51cf39e2b87447b7e65](https://www.blocktrail.com/BTC/tx/e543211b18e5d29fd3de7c0242cb017115f6a22ad5c6d51cf39e2b87447b7e65)
+
+`OP_RETURN` wire format (2 variations allowed):
+
+Variation 1:
+```
+ 0 2 3 39
+ |----|--|-----------------------------|
+ magic op name.ns_id (37 bytes)
+```
+
+Variation 2:
+```
+ 0 2 3 39 59
+ |----|--|----------------------------------|-------------------|
+ magic op name.ns_id (37 bytes, 0-padded) value
+```
+
+Inputs:
+
+* Payer `scriptSig`'s
+
+Outputs:
+
+* `OP_RETURN` payload
+* `scriptPubkey` for the owner's addess. This can be a different address than
+ the current name owner (in which case, the name is renewed and transferred).
+* `scriptPubkey` for the payer's change
+* `scriptPubkey` for the burn address (to pay the name cost)
+
+Notes:
+
+* This transaction is identical to a `NAME_REGISTRATION`, except for the presence of the fourth output that pays for the name cost (to the burn address).
+* Variation 1 simply renews the name. Variation 2 will both renew the name and
+ set a new name value (in practice, the hash of a new zone file).
+* Both variations are supported. Variation 1 was designed for the time when
+ Bitcoin only supported 40-byte `OP_RETURN` outputs.
+* This operation can be used to transfer a name to a new address by setting the
+ second output (the first `scriptPubkey`) to be the `scriptPubkey` of the new
+ owner key.
+
+### NAME_UPDATE
+
+Op: `+`
+
+Description: This transaction sets the name state for a name to the given
+`value`. In practice, this is used to announce new DNS zone file hashes to the [Atlas
+network]({{ site.baseurl }}/core/atlas/overview.html).
+
+Example: [e2029990fa75e9fc642f149dad196ac6b64b9c4a6db254f23a580b7508fc34d7](https://www.blocktrail.com/BTC/tx/e2029990fa75e9fc642f149dad196ac6b64b9c4a6db254f23a580b7508fc34d7)
+
+`OP_RETURN` wire format:
+```
+ 0 2 3 19 39
+ |-----|--|-----------------------------------|-----------------------|
+ magic op hash128(name.ns_id,consensus hash) zone file hash
+```
+
+Note that `hash128(name.ns_id, consensus hash)` is the first 16 bytes of a SHA256 hash over the name concatenated to the hexadecimal string of the consensus hash (not the bytes corresponding to that hex string).
+See the [Method Glossary](#method-glossary) below.
+
+Example: `hash128("jude.id" + "8d8762c37d82360b84cf4d87f32f7754") == "d1062edb9ec9c85ad1aca6d37f2f5793"`.
+
+The 20 byte zone file hash is computed from zone file data by using `ripemd160(sha56(zone file data))`
+
+Inputs:
+* owner `scriptSig`
+* payment `scriptSig`'s
+
+Outputs:
+* `OP_RETURN` payload
+* owner's `scriptPubkey`
+* payment `scriptPubkey` change
+
+### NAME_TRANSFER
+
+Op: `>`
+
+Description: This transaction changes the public key hash that owns the name in
+BNS.
+
+Example: [7a0a3bb7d39b89c3638abc369c85b5c028d0a55d7804ba1953ff19b0125f3c24](https://www.blocktrail.com/BTC/tx/7a0a3bb7d39b89c3638abc369c85b5c028d0a55d7804ba1953ff19b0125f3c24)
+
+`OP_RETURN` wire format:
+```
+ 0 2 3 4 20 36
+ |-----|--|----|-------------------|---------------|
+ magic op keep hash128(name.ns_id) consensus hash
+ data?
+```
+
+Inputs:
+
+* Owner `scriptSig`
+* Payment `scriptSig`'s
+
+Outputs:
+
+* `OP_RETURN` payload
+* new name owner's `scriptPubkey`
+* old name owner's `scriptPubkey`
+* payment `scriptPubkey` change
+
+Notes:
+
+* The `keep data?` byte controls whether or not the name's 20-byte value is preserved. This value is either `>` to preserve it, or `~` to delete it.
+
+### NAME_REVOKE
+
+Op: `~`
+
+Description: This transaction destroys a registered name. Its name state value
+in BNS will be cleared, and no further transactions will be able to affect the
+name until it expires (if its namespace allows it to expire at all).
+
+Example: [eb2e84a45cf411e528185a98cd5fb45ed349843a83d39fd4dff2de47adad8c8f](https://www.blocktrail.com/BTC/tx/eb2e84a45cf411e528185a98cd5fb45ed349843a83d39fd4dff2de47adad8c8f)
+
+`OP_RETURN` wire format:
+```
+ 0 2 3 39
+ |----|--|-----------------------------|
+ magic op name.ns_id (37 bytes)
+```
+
+Inputs:
+
+* owner `scriptSig`
+* payment `scriptSig`'s
+
+Outputs:
+
+* `OP_RETURN` payload
+* owner `scriptPubkey`
+* payment `scriptPubkey` change
+
+### ANNOUNCE
+
+Op: `#`
+
+Description: This transaction does not affect any names in BNS, but it allows a
+user to send a message to other BNS nodes. In order for the message to be
+received, the following must be true:
+
+* The sender must have a BNS name
+* The BNS nodes must list the sender's BNS name as being a "trusted message
+ sender"
+* The message must have already been propagated through the [Atlas
+ network]({{ site.baseurl }}/core/atlas/overview.html). This transaction references it by content hash.
+
+`OP_RETURN` wire format:
+
+```
+ 0 2 3 23
+ |----|--|-----------------------------|
+ magic op ripemd160(sha256(message))
+```
+
+Inputs:
+
+* The payer `scriptSig`'s
+
+Outputs:
+
+* `OP_RETURN` payload
+* change `scriptPubKey`
+
+Notes:
+
+* The payer key should be an owner key for an existing name, since Blockstack users can subscribe to announcements from specific name-owners.
+
+### NAMESPACE_PREORDER
+
+Op: `*`
+
+Description: This transaction announces the *hash* of a new namespace. It is the
+first of three transactions that must be sent to create a namespace.
+
+Example: [5f00b8e609821edd6f3369ee4ee86e03ea34b890e242236cdb66ef6c9c6a1b28](https://www.blocktrail.com/BTC/tx/5f00b8e609821edd6f3369ee4ee86e03ea34b890e242236cdb66ef6c9c6a1b28)
+
+`OP_RETURN` wire format:
+```
+ 0 2 3 23 39
+ |-----|---|-----------------------------------------|----------------|
+ magic op hash_name(ns_id,script_pubkey,reveal_addr) consensus hash
+```
+
+Inputs:
+
+* Namespace payer `scriptSig`
+
+Outputs:
+
+* `OP_RETURN` payload
+* Namespace payer `scriptPubkey` change address
+* `p2pkh` script to the burn address `1111111111111111111114oLvT2`, whose public key hash is 0x00000000000000000000000000000000
+
+Notes:
+
+* The `reveal_addr` field is the address of the namespace revealer public key. The revealer private key will be used to generate `NAME_IMPORT` transactions.
+
+### NAMESPACE_REVEAL
+
+Op: `&`
+
+Description: This transaction reveals the namespace ID and namespace rules
+for a previously-anounced namespace hash (sent by a previous `NAMESPACE_PREORDER`).
+
+Example: [ab54b1c1dd5332dc86b24ca2f88b8ca0068485edf0c322416d104c5b84133a32](https://www.blocktrail.com/BTC/tx/ab54b1c1dd5332dc86b24ca2f88b8ca0068485edf0c322416d104c5b84133a32)
+
+`OP_RETURN` wire format:
+```
+ 0 2 3 7 8 9 10 11 12 13 14 15 16 17 18 20 39
+ |-----|---|--------|-----|-----|----|----|----|----|----|-----|-----|-----|--------|----------|-------------------------|
+ magic op life coeff. base 1-2 3-4 5-6 7-8 9-10 11-12 13-14 15-16 nonalpha version namespace ID
+ bucket exponents no-vowel
+ discounts
+```
+
+Inputs:
+
+* Namespace payer `scriptSig`s
+
+Outputs:
+
+* `OP_RETURN` payload
+* namespace revealer `scriptPubkey`
+* namespace payer change `scriptPubkey`
+
+Notes:
+
+* This transaction must be sent within 1 day of the `NAMESPACE_PREORDER`
+* The second output (with the namespace revealer) **must** be a `p2pkh` script
+* The address of the second output **must** be the `reveal_addr` in the `NAMESPACE_PREORDER`
+
+Pricing:
+
+The rules for a namespace are as follows:
+
+ * a name can fall into one of 16 buckets, measured by length. Bucket 16 incorporates all names at least 16 characters long.
+ * the pricing structure applies a multiplicative penalty for having numeric characters, or punctuation characters.
+ * the price of a name in a bucket is ((coeff) * (base) ^ (bucket exponent)) / ((numeric discount multiplier) * (punctuation discount multiplier))
+
+Example:
+* base = 10
+* coeff = 2
+* nonalpha discount: 10
+* no-vowel discount: 10
+* buckets 1, 2: 9
+* buckets 3, 4, 5, 6: 8
+* buckets 7, 8, 9, 10, 11, 12, 13, 14: 7
+* buckets 15, 16+:
+
+With the above example configuration, the following are true:
+
+* The price of "john" would be 2 * 10^8, since "john" falls into bucket 4 and has no punctuation or numerics.
+* The price of "john1" would be 2 * 10^6, since "john1" falls into bucket 5 but has a number (and thus receives a 10x discount)
+* The price of "john_1" would be 2 * 10^6, since "john_1" falls into bucket 6 but has a number and punctuation (and thus receives a 10x discount)
+* The price of "j0hn_1" would be 2 * 10^5, since "j0hn_1" falls into bucket 6 but has a number and punctuation and lacks vowels (and thus receives a 100x discount)
+
+
+### NAME_IMPORT
+
+Op: `;`
+
+Description: This transaction registers a name and some name state into a
+namespace that has been revealed, but not been launched. Only the namespace
+creator can import names. See the [namespace creation section]({{ site.baseurl }}/core/naming/namespace.html) for details.
+
+Example: [c698ac4b4a61c90b2c93dababde867dea359f971e2efcf415c37c9a4d9c4f312](https://www.blocktrail.com/BTC/tx/c698ac4b4a61c90b2c93dababde867dea359f971e2efcf415c37c9a4d9c4f312)
+
+`OP_RETURN` wire format:
+```
+ 0 2 3 39
+ |----|--|-----------------------------|
+ magic op name.ns_id (37 bytes)
+```
+
+Inputs:
+
+* The namespace reveal `scriptSig` (with the namespace revealer's public key), or one of its first 300 extended public keys
+* Any payment inputs
+
+Outputs:
+
+* `OP_RETURN` payload
+* recipient `scriptPubKey`
+* zone file hash (using the 20-byte hash in a standard `p2pkh` script)
+* payment change `scriptPubKey`
+
+Notes:
+
+* These transactions can only be sent between the `NAMESPACE_REVEAL` and `NAMESPACE_READY`.
+* The first `NAME_IMPORT` transaction **must** have a `scriptSig` input that matches the `NAMESPACE_REVEAL`'s second output (i.e. the reveal output).
+* Any subsequent `NAME_IMPORT` transactions **may** have a `scriptSig` input whose public key is one of the first 300 extended public keys from the `NAMESPACE_REVEAL`'s `scriptSig` public key.
+
+### NAMESPACE_READY
+
+Op: `!`
+
+Description: This transaction launches a namesapce. Only the namespace creator
+can send this transaction. Once sent, anyone can register names in the
+namespace.
+
+Example: [2bf9a97e3081886f96c4def36d99a677059fafdbd6bdb6d626c0608a1e286032](https://www.blocktrail.com/BTC/tx/2bf9a97e3081886f96c4def36d99a677059fafdbd6bdb6d626c0608a1e286032)
+
+`OP_RETURN` wire format:
+```
+
+ 0 2 3 4 23
+ |-----|--|--|------------|
+ magic op . ns_id
+```
+
+Inputs:
+* Namespace revealer's `scriptSig`s
+
+Outputs:
+* `OP_RETURN` payload
+* Change output to the namespace revealer's `p2pkh` script
+
+Notes:
+* This transaction must be sent within 1 year of the corresponding `NAMESPACE_REVEAL` to be accepted.
+
+## Method Glossary
+
+Some hashing primitives are used to construct the wire-format representation of each name operation. They are enumerated here:
+
+```
+B40_REGEX = '^[a-z0-9\-_.+]*$'
+
+def is_b40(s):
+ return isinstance(s, str) and re.match(B40_REGEX, s) is not None
+
+def b40_to_bin(s):
+ if not is_b40(s):
+ raise ValueError('{} must only contain characters in the b40 char set'.format(s))
+ return unhexlify(charset_to_hex(s, B40_CHARS))
+
+def hexpad(x):
+ return ('0' * (len(x) % 2)) + x
+
+def charset_to_hex(s, original_charset):
+ return hexpad(change_charset(s, original_charset, B16_CHARS))
+
+def bin_hash160(s, hex_format=False):
+ """ s is in hex or binary format
+ """
+ if hex_format and is_hex(s):
+ s = unhexlify(s)
+ return hashlib.new('ripemd160', bin_sha256(s)).digest()
+
+def hex_hash160(s, hex_format=False):
+ """ s is in hex or binary format
+ """
+ if hex_format and is_hex(s):
+ s = unhexlify(s)
+ return hexlify(bin_hash160(s))
+
+def hash_name(name, script_pubkey, register_addr=None):
+ """
+ Generate the hash over a name and hex-string script pubkey.
+ Returns the hex-encoded string RIPEMD160(SHA256(x)), where
+ x is the byte string composed of the concatenation of the
+ binary
+ """
+ bin_name = b40_to_bin(name)
+ name_and_pubkey = bin_name + unhexlify(script_pubkey)
+
+ if register_addr is not None:
+ name_and_pubkey += str(register_addr)
+
+ # make hex-encoded hash
+ return hex_hash160(name_and_pubkey)
+
+def hash128(data):
+ """
+ Hash a string of data by taking its 256-bit sha256 and truncating it to the
+ first 16 bytes
+ """
+ return hexlify(bin_sha256(data)[0:16])
+```
diff --git a/_core/.svn/pristine/b8/b8a537d49a37ba34fde471cd04692b227666f70c.svn-base b/_core/.svn/pristine/b8/b8a537d49a37ba34fde471cd04692b227666f70c.svn-base
new file mode 100644
index 00000000..96af2a62
--- /dev/null
+++ b/_core/.svn/pristine/b8/b8a537d49a37ba34fde471cd04692b227666f70c.svn-base
@@ -0,0 +1,145 @@
+---
+layout: core
+permalink: /:collection/:path.html
+---
+# Blockstack Naming Service (BNS)
+{:.no_toc}
+
+This document gives an overview of how the Blockstack Naming Service work. This
+section introduces you to BNS and explains the following concepts:
+
+* TOC
+{:toc}
+
+The ([Blockstack Core](https://github.com/blockstack/blockstack-core))
+repository is the reference implementation of the Blockstack Naming Service.
+
+
+## What is BNS
+
+The Blockstack Naming Service (BNS) is a network system that binds names
+to off-chain state without relying on any central points of control.
+It does so by embedding a log of its control-plane messages within a public blockchain, like Bitcoin.
+
+Each BNS peer determines the state of each name by indexing these specially-crafted
+transactions. In doing so, each peer independently calculates the same global
+name state.
+
+Names in BNS have three properties:
+
+* **Names are globally unique.** The protocol does not allow name collisions, and all
+ well-behaved nodes resolve a given name to the same state.
+* **Names are human-meaningful.** Each name is chosen by its creator.
+* **Names are strongly-owned.** Only the name's owner can change the state it
+ resolves to. Specifically, a name is owned by one or more ECDSA private keys.
+
+Internally, a BNS node implements a replicated name database. Each BNS node keeps itself
+synchronized to all of the other ones in the world, so queries on one BNS node
+will be the same on other nodes. BNS nodes allow a name's owner to bind
+up to 40Kb of off-chain state to their name, which will be replicated to all
+BNS nodes via the [Atlas network]({{ site.baseurl }}/core/atlas/overview.html).
+
+BNS nodes extract the name database log from an underlying blockchain (Blockstack
+Core currently uses Bitcoin, and had used Namecoin in the past).
+BNS uses the blockchain to establish a shared "ground truth" for the system: as long as
+two nodes have the same view of the blockchain, then they will build up the same
+database.
+
+The biggest consequence for developers is that in BNS, reading name state is
+fast and cheap but writing name state is slow and expensive. This is because
+registering and modifying names requires one or more transactions to be sent to
+the underlying blockchain, and BNS nodes will not process them until they are
+sufficiently confirmed. Users and developers need to acquire and spend
+the requisite cryptocurrency (i.e. Bitcoin) to send BNS transactions.
+
+## Motivation behind naming services
+
+We rely on naming systems in everyday life, and they play a critical
+role in many different applications. For example, when you look up a
+friend on social media, you are using the platform's naming service to resolve
+their name to their profile. When you look up a website, you are using the
+Domain Name Service to
+resolve the hostname to its host's IP address. When you check out a Git branch, you
+are using your Git client to resolve the branch name to a commit hash.
+When you look up someone's PGP key on a keyserver, you are resolving
+their key ID to their public key.
+
+What kinds of things do we want to be true about names? In BNS, names are
+globally unique, names are human-meaningful, and names are strongly-owned.
+However, if you look at these examples, you'll see that each of them only
+guarantees *two* of these properties. This limits how useful they can be.
+
+* In DNS and social media, names are globally unique and human-readable, but not
+strongly-owned. The system operator has the
+final say as to what each names resolves to.
+ * **Problem**: Clients must trust the system to make the right
+ choice in what a given name resolves to. This includes trusting that
+ no one but the system administrators can make these changes.
+
+* In Git, branch names are human-meaningful
+and strongly-owned, but not globally unique. Two different Git nodes may resolve the same
+branch name to different unrelated repository states.
+ * **Problem**: Since names can refer to conflicting state, developers
+ have to figure out some other mechanism to resolve ambiguities. In Git's
+ case, the user has to manually intervene.
+
+* In PGP, names are key IDs. They are
+are globally unique and cryptographically owned, but not human-readable. PGP
+key IDs are derived from the keys they reference.
+ * **Problem**: These names are difficult for most users to
+ remember since they do not carry semantic information relating to their use in the system.
+
+BNS names have all three properties, and none of these problems. This makes it a
+powerful tool for building all kinds of network applications. With BNS, we
+can do the following and more:
+
+* Build domain name services where hostnames can't be hijacked.
+* Build social media platforms where user names can't be stolen by phishers.
+* Build version control systems where repository branches do not conflict.
+* Build public-key infrastructure where it's easy for users to discover and
+ remember each other's keys.
+
+
+# Organization of BNS
+
+BNS names are organized into a global name hierarchy. There are three different
+layers in this hierarchy related to naming:
+
+* **Namespaces**. These are the top-level names in the hierarchy. An analogy
+ to BNS namespaces are DNS top-level domains. Existing BNS namespaces include
+`.id`, `.podcast`, and `.helloworld`. All other names belong to exactly one
+namespace. Anyone can create a namespace, but in order for the namespace
+to be persisted, it must be *launched* so that anyone can register names in it.
+Namespaces are not owned by their creators.
+
+* **BNS names**. These are names whose records are stored directly on the
+ blockchain. The ownership and state of these names are controlled by sending
+blockchain transactions. Example names include `verified.podcast` and
+`muneeb.id`. Anyone can create a BNS name, as long as the namespace that
+contains it exists already. The state for BNS names is usually stored in the [Atlas
+network]({{ site.baseurl }}/core/atlas/overview.html).
+
+* **BNS subdomains**. These are names whose records are stored off-chain,
+but are collectively anchored to the blockchain. The ownership and state for
+these names lives within the [Atlas network]({{ site.baseurl }}/core/atlas/overview.html). While BNS
+subdomains are owned by separate private keys, a BNS name owner must
+broadcast their subdomain state. Example subdomains include `jude.personal.id`
+and `podsaveamerica.verified.podcast`. Unlike BNS namespaces and names, the
+state of BNS subdomains is *not* part of the blockchain consensus rules.
+
+A feature comparison matrix summarizing the similarities and differences
+between these name objects is presented below:
+
+| Feature | **Namespaces** | **BNS names** | **BNS Subdomains** |
+|---------|----------------|---------------|--------------------|
+| Globally unique | X | X | X |
+| Human-meaningful | X | X | X |
+| Owned by a private key | | X | X |
+| Anyone can create | X | X | [1] |
+| Owner can update | | X | [1] |
+| State hosted on-chain | X | X | |
+| State hosted off-chain | | X | X |
+| Behavior controlled by consensus rules | X | X | |
+| May have an expiration date | | X | |
+
+[1] Requires the cooperation of a BNS name owner to broadcast its transactions
diff --git a/_core/.svn/pristine/c3/c30c6f6eba9f7dc8c6c4561bb25fdeff9201fe1c.svn-base b/_core/.svn/pristine/c3/c30c6f6eba9f7dc8c6c4561bb25fdeff9201fe1c.svn-base
new file mode 100644
index 00000000..de87cfe9
--- /dev/null
+++ b/_core/.svn/pristine/c3/c30c6f6eba9f7dc8c6c4561bb25fdeff9201fe1c.svn-base
@@ -0,0 +1,36 @@
+doctype
+
+include mixins.jade
+
+html
+ head
+ meta(charset="utf-8")
+ title= self.api.name || 'API Documentation'
+ link(rel="stylesheet", href="https://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css")
+ style!= self.css
+ body.preload
+ #nav-background
+ div.container-fluid.triple
+ .row
+ block nav
+ +Nav(false)
+
+ .content
+ #right-panel-background
+
+ block content
+ +ContentTriple(false)
+
+ .middle
+ p.text-muted(style="text-align: center;")
+
+ script: include scripts.js
+
+ if self.livePreview
+ script(src="/socket.io/socket.io.js")
+ script.
+ var socket = io();
+ socket.on('refresh', refresh);
+ socket.on('reconnect', function () {
+ socket.emit('request-refresh');
+ });
diff --git a/_core/.svn/pristine/c4/c43d0d33ea4c1e6ba640a57da831fabcd59a2f77.svn-base b/_core/.svn/pristine/c4/c43d0d33ea4c1e6ba640a57da831fabcd59a2f77.svn-base
new file mode 100644
index 00000000..70435abc
--- /dev/null
+++ b/_core/.svn/pristine/c4/c43d0d33ea4c1e6ba640a57da831fabcd59a2f77.svn-base
@@ -0,0 +1,1123 @@
+# Group Core Node Administration
+
+Blockstack Core's API module provides a set of API calls for interacting with
+the node's configuration. Most configuration state is in the [Blockstack
+Browser](https://github.com/blockstack/blockstack-browser). Client-side state
+is managed by [blockstack.js](https://github.com/blockstack/blockstack.js).
+
+## Ping the node [GET /v1/node/ping]
+
+Ping the Blockstack node to see if it's alive.
+
++ Public Endpoint
++ Response 200 (application/json)
+ + Body
+
+ {
+ "status": "alive",
+ "version": "###version###"
+ }
+ + Schema
+
+ {
+ "type": "object",
+ "properties": {
+ "status": {
+ "type": "string"
+ },
+ "version": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "status",
+ "version"
+ ]
+ }
+
+# Group Managing Names
+
+## Fetch zone file [GET /v1/names/{name}/zonefile]
+
+Fetch a user's raw zone file. This only works for RFC-compliant zone files.
+This method returns an error for names that have non-standard zone files.
+
++ Public Endpoint
++ Parameters
+ + name: bar.test (string) - fully-qualified name
++ Response 200 (application/json)
+ + Body
+
+ {
+ "zonefile": "$ORIGIN bar.test\n$TTL 3600\n_https._tcp URI 10 1 \"https://blockstack.s3.amazonaws.com/bar.test\"\n"
+ }
+
+ + Schema
+
+ {
+ 'anyOf': [
+ {
+ 'type': 'object',
+ 'properties': {
+ 'zonefile': {
+ 'type': 'string',
+ 'pattern': '.+',
+ },
+ },
+ {
+ 'type': 'object',
+ 'properties': {
+ 'error': {
+ 'type': 'string',
+ 'pattern': '.+',
+ },
+ },
+ ]
+ }
+
+# Group Name Querying
+
+This family of API endpoints deals with querying name information.
+
+## Get all names [GET /v1/names?page={page}]
+Fetch a list of all names known to the node.
++ Public Endpoint
++ Parameters
+ + page: 23 (number) - names are returned in pages of size 100,
+ so specify the page number.
++ Response 200 (application/json)
+ + Body
+
+ [ "aldenquimby.id", "aldeoryn.id",
+ "alderete.id", "aldert.id",
+ "aldi.id", "aldighieri.id", ... ]
+
+ + Schema
+
+ {
+ 'type': 'array',
+ 'items': {
+ 'type': 'string',
+ 'pattern': r'^([a-z0-9\\-_.+]{3,37})$',
+ }
+ }
+
+## Get all subdomains [GET /v1/subdomains?page={page}]
+Fetch a list of all names known to the node.
++ Public Endpoint
++ Parameters
+ + page: 3 (number) - names are returned in pages of size 100,
+ so specify the page number.
++ Response 200 (application/json)
+ + Body
+
+ [
+ "collegeinfogeek.verified.podcast",
+ "collider.verified.podcast",
+ "combatandclassics.verified.podcast",
+ "combatjack.verified.podcast",
+ "comedybangbang.verified.podcast",
+ "comedybutton.verified.podcast",
+ "commonsense.verified.podcast",
+ "concilio002.personal.id", ... ]
+
+ + Schema
+
+ {
+ 'type': 'array',
+ 'items': {
+ 'type': 'string',
+ 'pattern': r'^([a-z0-9\\-_.+]{3,37})\.([a-z0-9\\-_.+]{3,37})$',
+ }
+ }
+
+## Get name info [GET /v1/names/{name}]
++ Public Endpoint
++ Subdomain Aware
++ Parameters
+ + name: muneeb.id (string) - fully-qualified name
++ Response 200 (application/json)
+ + Body
+
+ {
+ "address": "1QJQxDas5JhdiXhEbNS14iNjr8auFT96GP",
+ "blockchain": "bitcoin",
+ "expire_block": 489247,
+ "last_txid": "1edfa419f7b83f33e00830bc9409210da6c6d1db60f99eda10c835aa339cad6b",
+ "status": "registered",
+ "zonefile": "$ORIGIN muneeb.id\n$TTL 3600\n_http._tcp IN URI 10 1 \"https://blockstack.s3.amazonaws.com/muneeb.id\"\n",
+ "zonefile_hash": "b100a68235244b012854a95f9114695679002af9"
+ }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'address': {
+ 'type': 'string',
+ 'pattern': r"^([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]+)$",
+ },
+ 'blockchain': {
+ 'type': 'string',
+ 'pattern': '^bitcoin$',
+ },
+ 'expire_block': {
+ 'type': 'integer',
+ 'minimum': 0,
+ },
+ 'last_txid': {
+ 'type': 'string',
+ 'pattern': '^[0-9a-fA-F]+$',
+ },
+ 'status': {
+ 'type': 'string',
+ 'pattern': '^(registered|revoked)$',
+ },
+ 'zonefile': {
+ 'anyOf': [
+ {
+ 'type': 'string',
+ },
+ {
+ 'type': 'object',
+ 'properties': {
+ 'error': {
+ 'type': 'string',
+ },
+ },
+ },
+ ],
+ },
+ 'zonefile_hash': {
+ 'type': 'string',
+ 'pattern': '^[0-9a-fA-F]{20}$`,
+ },
+ },
+ { 'required':
+ [
+ 'address', 'blockchain', 'last_txid',
+ 'status', 'zonefile', 'zonefile_hash'
+ ]
+ }
+ }
+
+## Get name history [GET /v1/names/{name}/history?page={page}]
+Get a history of all blockchain records of a registered name.
++ Public Endpoint
++ Subdomain aware
++ Parameters
+ + name: muneeb.id (string) - name to query
+ + page: 0 (integer) - the page (in 20-entry pages) of the history to fetch
++ Response 200 (application/json)
+ + Body
+
+ {
+ "373821": [
+ {
+ "address": "1QJQxDas5JhdiXhEbNS14iNjr8auFT96GP",
+ "block_number": 373821,
+ "consensus_hash": null,
+ "first_registered": 373821,
+ "importer": "76a9143e2b5fdd12db7580fb4d3434b31d4fe9124bd9f088ac",
+ "importer_address": "16firc3qZU97D1pWkyL6ZYwPX5UVnWc82V",
+ "last_creation_op": ";",
+ "last_renewed": 373821,
+ "name": "muneeb.id",
+ "name_hash128": "deb7fe99776122b77925cbf0a24ab6f8",
+ "namespace_block_number": 373601,
+ "namespace_id": "id",
+ "op": ";",
+ "op_fee": 100000.0,
+ "opcode": "NAME_IMPORT",
+ "preorder_block_number": 373821,
+ }
+ ]
+ }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'patternProperties': {
+ '^[0-9]+': {
+ 'type': 'array',
+ 'items': {
+ 'type': 'object',
+ 'properties': {
+ 'address': {
+ 'type': 'string',
+ 'pattern': r"^([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]+)$",
+ },
+ 'base': {
+ 'type': 'integer',
+ 'minimum': 0,
+ 'maximum': 255,
+ },
+ 'buckets': {
+ 'anyOf': [
+ {
+ 'type': 'array',
+ 'items': {
+ 'type': 'integer',
+ 'minItems': 16,
+ 'maxItems': 16,
+ },
+ },
+ {
+ 'type': 'null',
+ },
+ ],
+ },
+ 'block_number': {
+ 'type': 'integer',
+ 'minimum': 0,
+ },
+ 'coeff': {
+ 'anyOf': [
+ {
+ 'type': 'integer',
+ 'minimum': 0,
+ 'maximum': 255,
+ },
+ {
+ 'type': 'null'
+ },
+ ],
+ },
+ 'consensus_hash': {
+ 'anyOf': [
+ {
+ 'type': 'string',
+ 'pattern': '^[0-9a-fA-F]{32}',
+ },
+ {
+ 'type': 'null'
+ },
+ ],
+ },
+ 'fee': {
+ 'type': 'integer',
+ 'minimum': 0,
+ },
+ 'first_registered': {
+ 'type': 'integer',
+ 'minimum': 0,
+ },
+ 'history_snapshot': {
+ 'type': 'boolean',
+ },
+ 'importer': {
+ 'anyOf': [
+ {
+ 'type': 'string',
+ 'pattern': r'^76[aA]914[0-9a-fA-F]{40}88[aA][cC]$',
+ },
+ {
+ 'type': 'null',
+ },
+ ],
+ },
+ 'importer_address': {
+ 'anyOf': [
+ {
+ 'type': 'string',
+ 'pattern': r"^([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]+)$",
+ },
+ {
+ 'type': 'null',
+ },
+ ],
+ },
+ 'last_renewed': {
+ 'type': 'integer',
+ 'minimum': 0,
+ },
+ 'op': {
+ 'type': 'string',
+ 'pattern': '^([>?+~:!&*:;#]{1}|>>|>~|::)$',
+ },
+ 'op_fee': {
+ 'type': 'number',
+ },
+ 'opcode': {
+ 'type': 'string',
+ 'pattern': '^NAME_TRANSFER|NAME_PREORDER|NAME_UPDATE|NAME_REVOKE|NAME_REGISTRATION|NAMESPACE_READY|NAMESPACE_REVEAL|NAMESPACE_PREORDER|NAME_RENEWAL|NAME_IMPORT|ANNOUNCE$'
+ },
+ 'revoked': {
+ 'type': 'boolean',
+ },
+ 'sender': {
+ 'type': 'string',
+ 'pattern': '^([0-9a-fA-F]+)$',
+ },
+ 'sender_pubkey': {
+ 'anyOf': [
+ {
+ 'type': 'string',
+ 'pattern': '^([0-9a-fA-F]+)$',
+ },
+ {
+ 'type': 'null'
+ },
+ ],
+ },
+ 'recipient': {
+ 'anyOf': [
+ {
+ 'type': 'string',
+ 'pattern': '^([0-9a-fA-F]+)$',
+ },
+ {
+ 'type': 'null'
+ },
+ ],
+ },
+ 'recipient_address': {
+ 'anyOf': [
+ {
+ 'type': 'string',
+ 'pattern': '^([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]+)$',
+ },
+ {
+ 'type': 'null'
+ },
+ ],
+ },
+ 'recipient_pubkey': {
+ 'anyOf': [
+ {
+ 'type': 'string',
+ 'pattern': '^([0-9a-fA-F]+)$',
+ },
+ {
+ 'type': 'null'
+ },
+ ],
+ },
+ 'txid': {
+ 'type': 'string',
+ 'pattern': '^([0-9a-fA-F]+)$',
+ },
+ 'value_hash': {
+ 'anyOf': [
+ {
+ 'type': 'string',
+ 'pattern': '^([0-9a-fA-F]{40})$',
+ },
+ {
+ 'type': 'null',
+ },
+ ],
+ },
+ 'vtxindex': {
+ 'type': 'integer',
+ 'minimum': 0,
+ },
+ },
+ 'required': [
+ 'op',
+ 'opcode',
+ 'txid',
+ 'vtxindex'
+ ],
+ }
+ }
+ }
+ }
+
+## Get historical zone file [GET /v1/names/{name}/zonefile/{zoneFileHash}]
+Fetches the historical zonefile specified by the username and zone hash.
++ Public Endpoint
++ Subdomain aware
++ Parameters
+ + name: muneeb.id (string) username to fetch
+ + zoneFileHash: b100a68235244b012854a95f9114695679002af9
++ Response 200 (application/json)
+ + Body
+
+ {
+ "zonefile":
+ "$ORIGIN muneeb.id\n$TTL 3600\n_http._tcp IN URI 10 1 \"https://blockstack.s3.amazonaws.com/muneeb.id\"\n"
+ }
+
+ + Schema
+
+ {
+ 'anyOf': [
+ {
+ 'type': 'object',
+ 'properties': {
+ 'zonefile': { 'type': 'string' },
+ },
+ },
+ {
+ 'type': 'object',
+ 'properties': {
+ 'error': { 'type': 'string' },
+ },
+ },
+ ],
+ }
+
+## Get names owned by address [GET /v1/addresses/{blockchain}/{address}]
+Retrieves a list of names owned by the address provided.
++ Subdomain Aware
++ Public Endpoint
++ Parameters
+ + blockchain: bitcoin (string) - the layer-1 blockchain for the address
+ + address: 1QJQxDas5JhdiXhEbNS14iNjr8auFT96GP (string) - the address to lookup
+
++ Response 200 (application/json)
+ + Body
+
+ {
+ "names": ["muneeb.id"]
+ }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'names': {
+ 'type': 'array',
+ 'items': {
+ 'type': 'string',
+ 'pattern': '^([a-z0-9\-_.+]{3,37})$',
+ },
+ },
+ },
+ }
+
+# Group Price Checks
+
+## Get namespace price [GET /v1/prices/namespaces/{tld}]
+
+This endpoint is used to get the price of a namespace. Anyone can create a
+namespace by following [this
+tutorial](https://github.com/blockstack/blockstack-core/blob/master/docs/namespace_creation.md).
+
++ Public Endpoint
++ Parameters
+ + tld: id (string) - namespace to query price for
++ Response 200 (application/json)
+ + Body
+
+ {
+ "satoshis": 4000000000
+ }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'satoshis': {
+ 'type': 'integer',
+ 'minimum': 0,
+ },
+ },
+ }
+
+## Get name price [GET /v1/prices/names/{name}]
+
+This endpoint is used to get the price of a name. If you are using a public
+endpoint, you should *only* rely on the `name_price` field in the returned JSON
+blob.
+
+The other fields are relevant only for estimating the cost of registering a
+name. You register a name via
+[blockstack.js](https://github.com/blockstack/blockstack.js) or the [Blockstack
+Browser](https://github.com/blockstack/blockstack-browser)).
+
++ Public Endpoint
++ Parameters
+ + name: muneeb.id (string) - name to query price information for
++ Response 200 (application/json)
+ + Body
+
+ {
+ "name_price": {
+ "satoshis": 100000,
+ "btc": 0.001
+ },
+ "total_tx_fees": 519209,
+ "register_tx_fee": {
+ "satoshis": 159110,
+ "btc": 0.0015911
+ },
+ "preorder_tx_fee": {
+ "satoshis": 163703,
+ "btc": 0.00163703
+ },
+ "warnings": [
+ "Insufficient funds; fees are rough estimates."
+ ],
+ "total_estimated_cost": {
+ "satoshis": 619209,
+ "btc": 0.00619209
+ },
+ "update_tx_fee": {
+ "satoshis": 196396,
+ "btc": 0.00196396
+ }
+ }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'name_price': {
+ 'type': 'object',
+ 'properties': {
+ 'btc': { 'type': 'number', 'minimum': 0 },
+ 'satoshis': { 'type': 'integer', 'minimum': 0 }
+ }
+ },
+ 'preorder_tx_fee': {
+ 'type': 'object',
+ 'properties': {
+ 'btc': { 'type': 'number', 'minimum': 0 },
+ 'satoshis': { 'type': 'integer', 'minimum': 0 }
+ }
+ },
+ 'register_tx_fee': {
+ 'type': 'object',
+ 'properties': {
+ 'btc': { 'type': 'number', 'minimum': 0 },
+ 'satoshis': { 'type': 'integer', 'minimum': 0 }
+ }
+ },
+ 'update_tx_fee': {
+ 'type': 'object',
+ 'properties': {
+ 'btc': { 'type': 'number', 'minimum': 0 },
+ 'satoshis': { 'type': 'integer', 'minimum': 0 }
+ }
+ },
+ 'total_estimated_cost': {
+ 'type': 'object',
+ 'properties': {
+ 'btc': { 'type': 'number', 'minimum': 0 },
+ 'satoshis': { 'type': 'integer', 'minimum': 0 }
+ }
+ },
+ 'total_tx_fees': {
+ 'type': 'integer',
+ 'minimum': 0,
+ }
+ 'name_price': {
+ 'type': 'object',
+ 'properties': {
+ 'btc': { 'type': 'number', 'minimum': 0 },
+ 'satoshis': { 'type': 'integer', 'minimum': 0 }
+ }
+ },
+ 'warnings': {
+ 'type': 'array',
+ 'items': {
+ 'type': 'string',
+ },
+ },
+ },
+ }
+
+# Group Blockchain Operations
+
+## Get consensus hash [GET /v1/blockchains/{blockchainName}/consensus]
+
+Get the current Blockstack consensus hash on a blockchain.
++ Public Endpoint
++ Parameters
+ + blockchainName : bitcoin (string) - the given blockchain
++ Response 200 (application/json)
+ + Body
+
+ {
+ "consensus_hash": "2fcbdf66c350894fe03b42c6a2e8a6ac"
+ }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'consensus_hash': {
+ 'type': 'string',
+ 'pattern': '^[0-9a-fA-F]{32}$`,
+ },
+ },
+ }
+
+## Get total names on Blockchain [GET /v1/blockchains/{blockchainName}/name_count{?all}]
+
+Get a count of the number of names on a blockchain.
++ Public Endpoint
++ Parameters
+ + blockchainName: bitcoin (string) - the given blockchain
+ + all: true (enum[string], optional) - include expired names
++ Response 200 (application/json)
+ + Body
+
+ {
+ "names_count": 73950
+ }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'names_count': {
+ 'type': 'integer',
+ 'minimum': 0,
+ },
+ },
+ }
+
++ Response 401 (application/json)
+ + Body
+
+ { "error": "Unsupported blockchain" }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'error': { 'type': 'string' },
+ },
+ },
+
+
+## Get number of subdomains on blockchain [GET /v1/blockchains/{blockchainName}/subdomains_count]
+Get the number of subdomains on a blockchain.
++ Public Endpoint
++ Parameters
+ + blockchainName: bitcoin (string) - the given blockchain
++ Response 200 (application/json)
+ + Body
+
+ {
+ "names_count": 1646
+ }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'names_count': {
+ 'type': 'integer',
+ 'minimum': 0,
+ },
+ },
+ }
+
++ Response 401 (application/json)
+ + Body
+
+ { "error": "Unsupported blockchain" }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'error': { 'type': 'string' },
+ },
+ },
+
+
+## Get operations in block [GET /v1/blockchains/{blockchainName}/operations/{blockHeight}]
+
+Get the Blockstack operations in a given block
++ Public Endpoint
++ Parameters
+ + blockchainName : bitcoin (string) - the given blockchain
+ + blockHeight : 462592 (integer) - the block height
++ Response 200 (application/json)
+ + Body
+
+ [
+ {
+ "address": "1GS1eHthSK2gqnU9MW9Nis1pUyHP3bJnFK",
+ "block_number": 462592,
+ "burn_address": "1111111111111111111114oLvT2",
+ "consensus_hash": "d206b2f615de00803402cade4d0d51d4",
+ "op": "?",
+ "op_fee": 6250,
+ "opcode": "NAME_PREORDER",
+ "preorder_hash": "ba22cdf24b05b9a7972e13ada69f96a7850b471e",
+ "sender": "76a914a944d29012f83c00105778e0bc717c46ea2accfc88ac",
+ "sender_pubkey": "0343b263f7adc6ae59e8d8310f4a6a87799f6b10cec608f3236cd6a802ffc71728",
+ "txid": "b3f4f7a43d60666d1a9b42131f9117ad7deac34a478b6ca152344da3d734691f",
+ "vtxindex": 173
+ },
+ {
+ "address": "1gijbF8NkbgwzcoZR1nXMa76NbdcD7GQW",
+ "block_number": 462592,
+ "burn_address": "1111111111111111111114oLvT2",
+ "consensus_hash": "d206b2f615de00803402cade4d0d51d4",
+ "op": "?",
+ "op_fee": 6250,
+ "opcode": "NAME_PREORDER",
+ "preorder_hash": "386e2de88a908ad056361e586faa95852be454ca",
+ "sender": "76a91407830f81167f6a2aa253c0f176b7ff2e1c04c61a88ac",
+ "sender_pubkey": "03b7795d33b362338179e5b2a579431b285f6c303d07ddd83c897277be4e5eb916",
+ "txid": "4dd315ad1d1b318614a19e15e767efb7ef327bd5cd4ebaf8f80ede58fd1da107",
+ "vtxindex": 174
+ },
+ {
+ "address": "17QEd6rrhNZp4xoyWu6BpA8NQ4axyNKaZy",
+ "block_number": 462592,
+ "burn_address": "1111111111111111111114oLvT2",
+ "consensus_hash": "d206b2f615de00803402cade4d0d51d4",
+ "op": "?",
+ "op_fee": 6250,
+ "opcode": "NAME_PREORDER",
+ "preorder_hash": "a7a388a2bbe0e7741c6cfdc54d7b5a67811cd582",
+ "sender": "76a9144635b1794a22bfbe6c5c5eba17b693f4aaf0e34888ac",
+ "sender_pubkey": "020d6e50b2660af27933c42bc1395fe93df90ffac5e2a989f6a134919fb8cf8075",
+ "txid": "51d6bd117da5889e710c62967d03233a84fc27f7fad10ca4359111928818f017",
+ "vtxindex": 332
+ },
+ {
+ "address": "15YMyvqz6v9ATSbmqJnudwrdm7RiVfkU3s",
+ "block_number": 462453,
+ "consensus_hash": "f6491e1d2b9817fa58512fc9bf8cd3df",
+ "first_registered": 462575,
+ "importer": null,
+ "importer_address": null,
+ "keep_data": true,
+ "last_renewed": 462575,
+ "name": "ablankstein.id",
+ "name_hash128": "943b8e0613d975c05a05ccd5472e2a72",
+ "namespace_block_number": 373601,
+ "namespace_id": "id",
+ "op": ">>",
+ "op_fee": 25000,
+ "opcode": "NAME_TRANSFER",
+ "preorder_block_number": 462453,
+ "preorder_hash": "822d5cb6f2e3f0f901d6af8c1111ee466b6c07bd",
+ "revoked": false,
+ "sender": "76a91431cee995f242f0f66518080a291714cd7e8d2f5e88ac",
+ "sender_pubkey": null,
+ "txid": "121540e81223c45d139fbe03a9713ddd292372f2f88fe2b10b6a7c5e6738e87f",
+ "value_hash": "96ec93cbc57d17b16a347c11ddfa7ea88d2cf93b",
+ "vtxindex": 633
+ },
+ {
+ "address": "1Dwq9oA5BNz7DAR1LtDncEa647ZxgmkoVV",
+ "block_number": 462325,
+ "consensus_hash": "1288cef43f52bf97e2f458a4afe40b61",
+ "first_registered": 462359,
+ "importer": null,
+ "importer_address": null,
+ "keep_data": true,
+ "last_renewed": 462359,
+ "name": "fpenrose.id",
+ "name_hash128": "7af28a9834934a0af81a19ee14a45f8e",
+ "namespace_block_number": 373601,
+ "namespace_id": "id",
+ "op": ">>",
+ "op_fee": 25000,
+ "opcode": "NAME_TRANSFER",
+ "preorder_block_number": 462325,
+ "preorder_hash": "59c25d7cddf433b5122cabcbf2ebcc1bc1519e4d",
+ "revoked": false,
+ "sender": "76a9148e002a93b9b1936b5d320967194eaff3deaa979088ac",
+ "sender_pubkey": null,
+ "txid": "6461bb4bbf517e9c80ffcac4c349836972656572e113aba736b356119655064e",
+ "value_hash": "ac73155702ca7aea1161d0f0c7877ac81d48d8fc",
+ "vtxindex": 637
+ },
+ {
+ "address": "1Q44Md5KFr6gxQ6TdUSFaCRm3MaUyXMF6t",
+ "block_number": 462316,
+ "consensus_hash": "1288cef43f52bf97e2f458a4afe40b61",
+ "first_registered": 462353,
+ "importer": null,
+ "importer_address": null,
+ "keep_data": true,
+ "last_renewed": 462353,
+ "name": "rahulpradhan.id",
+ "name_hash128": "c55ff9e14c72b2950b14ff10067d7e27",
+ "namespace_block_number": 373601,
+ "namespace_id": "id",
+ "op": ">>",
+ "op_fee": 25000,
+ "opcode": "NAME_TRANSFER",
+ "preorder_block_number": 462316,
+ "preorder_hash": "fcb3389ca4d2ab8003ce8b6b3baa0a5ae1600cce",
+ "revoked": false,
+ "sender": "76a914fcdef125f40f984fafad4b58e30e3b1761a953f388ac",
+ "sender_pubkey": null,
+ "txid": "be58e02642c457fec2835a354fbc2de45e8c838aa5b7fd18ed831f67d08269e6",
+ "value_hash": "e213e58ca1446875b79d866720130cc90cbca681",
+ "vtxindex": 638
+ },
+ {
+ "address": "1D8pL725X9HWvoTVgzqDNbTPayHGG7tkY6",
+ "block_number": 462345,
+ "consensus_hash": "919df884f14f34fd15a791af2fddb569",
+ "first_registered": 462380,
+ "importer": null,
+ "importer_address": null,
+ "keep_data": true,
+ "last_renewed": 462380,
+ "name": "sajithskurup.id",
+ "name_hash128": "3fda1c60620c42e1ede385bb246bd5f0",
+ "namespace_block_number": 373601,
+ "namespace_id": "id",
+ "op": ">>",
+ "op_fee": 25000,
+ "opcode": "NAME_TRANSFER",
+ "preorder_block_number": 462345,
+ "preorder_hash": "540daefe1f3b520253f7ab954dbc8bf131471133",
+ "revoked": false,
+ "sender": "76a914851bee0185dd799755234fb20710a26ec40354d288ac",
+ "sender_pubkey": null,
+ "txid": "e7d35196ca3eec697274d848136f5267b1c935055a917020f93e8ecaf821ba99",
+ "value_hash": "92534954e934019718478bb52150765dfad79171",
+ "vtxindex": 644
+ },
+ {
+ "address": "1EbjXtYv9QCVBp8iWiDH6xQ1B74oFW696X",
+ "block_number": 462345,
+ "consensus_hash": "e0c31e03125f2feefd4090e5c635ee45",
+ "first_registered": 462380,
+ "importer": null,
+ "importer_address": null,
+ "keep_data": true,
+ "last_renewed": 462380,
+ "name": "hubject.id",
+ "name_hash128": "03e8bf92dd3cbde65cac012350efb79d",
+ "namespace_block_number": 373601,
+ "namespace_id": "id",
+ "op": ">>",
+ "op_fee": 25000,
+ "opcode": "NAME_TRANSFER",
+ "preorder_block_number": 462345,
+ "preorder_hash": "ded4d097614cf5321388bbe56b24d3d592b2ef76",
+ "revoked": false,
+ "sender": "76a914952b4844005dd98a1f7fc99813db2a649109b45988ac",
+ "sender_pubkey": null,
+ "txid": "7b7a2a2963f7454b93003031cfce64ac609f902b4c2cababfbbfad2c01bbeb9b",
+ "value_hash": "be968a1f17ac828179e5b2fbc70d238056af7482",
+ "vtxindex": 645
+ },
+ {
+ "address": "14YsDo5qgAP7kmnq33tw9JdHVBywpg9pge",
+ "block_number": 462326,
+ "consensus_hash": "e0c31e03125f2feefd4090e5c635ee45",
+ "first_registered": 462354,
+ "importer": null,
+ "importer_address": null,
+ "keep_data": true,
+ "last_renewed": 462354,
+ "name": "ramimassoud.id",
+ "name_hash128": "61a48b6f8aeb027883ecd1f8d808c8ac",
+ "namespace_block_number": 373601,
+ "namespace_id": "id",
+ "op": ">>",
+ "op_fee": 25000,
+ "opcode": "NAME_TRANSFER",
+ "preorder_block_number": 462326,
+ "preorder_hash": "23aa275e42d7d6d7e538584a799252939687c457",
+ "revoked": false,
+ "sender": "76a91426ef31b7aac60eff23cbbab51d453b84700e330388ac",
+ "sender_pubkey": null,
+ "txid": "85babcf66caf41cb7beb2e637cbed4e728ab8030337fb5df8461d0e14dd2be75",
+ "value_hash": "e27c9c3dcce8a8445d84fb8b4d81fbd30fac9749",
+ "vtxindex": 646
+ },
+ {
+ "address": "1H934mT7AVVZmHwjddUZ9EiostLwm655oF",
+ "block_number": 462345,
+ "consensus_hash": "919df884f14f34fd15a791af2fddb569",
+ "first_registered": 462391,
+ "importer": null,
+ "importer_address": null,
+ "keep_data": true,
+ "last_renewed": 462391,
+ "name": "was2bme.id",
+ "name_hash128": "f2b5688682fd47b8f3fbf709bb35ef33",
+ "namespace_block_number": 373601,
+ "namespace_id": "id",
+ "op": ">>",
+ "op_fee": 6250,
+ "opcode": "NAME_TRANSFER",
+ "preorder_block_number": 462345,
+ "preorder_hash": "3dfdcee2b0e64697c4bb0b0dd791518bcb078dc7",
+ "revoked": false,
+ "sender": "76a914b107105f8ae57e7bb5bad58caba666faa679c70f88ac",
+ "sender_pubkey": null,
+ "txid": "16171e4e20778354a94c5353b0c6ed0b29a3e73c1b59b9bfbcbe6d26c570fd0c",
+ "value_hash": "ac73155702ca7aea1161d0f0c7877ac81d48d8fc",
+ "vtxindex": 649
+ },
+ {
+ "address": "1B4zxvVMPm1PBGarc8PrYQjQY2ezwniyG6",
+ "block_number": 462345,
+ "consensus_hash": "e0c31e03125f2feefd4090e5c635ee45",
+ "first_registered": 462391,
+ "importer": null,
+ "importer_address": null,
+ "keep_data": true,
+ "last_renewed": 462391,
+ "name": "tadas_serbenta.id",
+ "name_hash128": "6d800932daf830925ab47dee5ceb8661",
+ "namespace_block_number": 373601,
+ "namespace_id": "id",
+ "op": ">>",
+ "op_fee": 6250,
+ "opcode": "NAME_TRANSFER",
+ "preorder_block_number": 462345,
+ "preorder_hash": "07a85eac4dbf20000a66a14a4a89a01134b70fab",
+ "revoked": false,
+ "sender": "76a9146e72e44bbe4c1706ea5830096a4bb4449dcc948f88ac",
+ "sender_pubkey": null,
+ "txid": "e3f0b019550417a7acfe27addfbd34ec7ec5fc1dd9616ed8c6bc86a0ad148290",
+ "value_hash": "fbac107ba5d9bbfc30ecdeae3e10ca3db72b3431",
+ "vtxindex": 855
+ },
+ {
+ "address": "16BF35VputeLEmbsk7gDnUcwKXcjwPDUvf",
+ "block_number": 462345,
+ "consensus_hash": "919df884f14f34fd15a791af2fddb569",
+ "first_registered": 462359,
+ "importer": null,
+ "importer_address": null,
+ "keep_data": true,
+ "last_renewed": 462359,
+ "name": "alexucf.id",
+ "name_hash128": "d9bc88b0fdc536e7ac5467609faed518",
+ "namespace_block_number": 373601,
+ "namespace_id": "id",
+ "op": ">>",
+ "op_fee": 25000,
+ "opcode": "NAME_TRANSFER",
+ "preorder_block_number": 462345,
+ "preorder_hash": "30f841114af6ada90ba720d563672113c4f74439",
+ "revoked": false,
+ "sender": "76a91438c8814ae2a9035e85bbf2b7976919c2e3387ac588ac",
+ "sender_pubkey": null,
+ "txid": "f8e9eebd48b9182b82b22e5ce10f805d3db38786bb2aaf56f9badf83aa3cc0ee",
+ "value_hash": "8ae0f51263f540be175230d6b46f5d9609de799d",
+ "vtxindex": 856
+ },
+ {
+ "address": "1EmXTRHC6f9bnLJkVZRavv7HLG1owLgNir",
+ "block_number": 462326,
+ "consensus_hash": "31a304b682e3291811441a12f19d14e5",
+ "first_registered": 462391,
+ "importer": null,
+ "importer_address": null,
+ "keep_data": true,
+ "last_renewed": 462391,
+ "name": "seamur.id",
+ "name_hash128": "09f3b9d2da3d0aa1999824f7884f0d18",
+ "namespace_block_number": 373601,
+ "namespace_id": "id",
+ "op": ">>",
+ "op_fee": 100000,
+ "opcode": "NAME_TRANSFER",
+ "preorder_block_number": 462326,
+ "preorder_hash": "678991fd4d3833babe27f732206a40d1f15dd3ca",
+ "revoked": false,
+ "sender": "76a91497055c47fa0ab396fb321e9d37f6bce1796e3d5688ac",
+ "sender_pubkey": null,
+ "txid": "e32124770c359eaf57709e5a666894f2954aa687820c41c6911f214e9006b58e",
+ "value_hash": "4bcdd931185537902ef1af9975198c6404d4c73e",
+ "vtxindex": 857
+ },
+ {
+ "address": "13pGtMcHsNdq3EeLMa1yVVKppP1WjSKgFG",
+ "block_number": 462345,
+ "consensus_hash": "e0c31e03125f2feefd4090e5c635ee45",
+ "first_registered": 462354,
+ "importer": null,
+ "importer_address": null,
+ "keep_data": true,
+ "last_renewed": 462354,
+ "name": "innergame.id",
+ "name_hash128": "a3e4e010d82369ee19b64fccc2b97f69",
+ "namespace_block_number": 373601,
+ "namespace_id": "id",
+ "op": ">>",
+ "op_fee": 25000,
+ "opcode": "NAME_TRANSFER",
+ "preorder_block_number": 462345,
+ "preorder_hash": "f54850caf10c3041cb2a4d9186bbb234dd7d9f85",
+ "revoked": false,
+ "sender": "76a9141ee10ff0ae9969e2dc39d94a959e3160b26b6adf88ac",
+ "sender_pubkey": null,
+ "txid": "28de7193e28e1b0c950a32af393284578669c15dc98bad68f382f8b920d94509",
+ "value_hash": "bab40c2b10f676288edea119edade67ff5e853ba",
+ "vtxindex": 869
+ }
+ ]
+
+
+# Group Namespace Operations
+
+## Get all namespaces [GET /v1/namespaces]
++ Public Endpoint
++ Response 200 (application/json)
+ + Body
+
+ {
+ "namespaces": [
+ ".id"
+ ]
+ }
+
+## Get namespace names [GET /v1/namespaces/{tld}/names?page={page}]
+
+Fetch a list of names from the namespace.
++ Public Endpoint
++ Parameters
+ + tld: id (string) - the namespace to fetch names from
+ + page: 23 (number) - names are returned in pages of size 100,
+ so specify the page number.
++ Response 200 (application/json)
+ + Body
+
+ [ "aldenquimby.id", "aldeoryn.id",
+ "alderete.id", "aldert.id",
+ "aldi.id", "aldighieri.id", ... ]
+
+# Group Resolver Endpoints
+
+## Lookup User [GET /v1/users/{username}]
+
+Lookup and resolver a user's profile. Defaults to the `id` namespace. Note that
+[blockstack.js](https://github.com/blockstack/blockstack.js) does *not* rely on
+this endpoint.
+
++ Public Only Endpoint
++ Subdomain Aware
++ Legacy Endpoint
++ Parameters
+ + username: fred (string) - username to lookup
++ Response 200 (application/json)
+ + Body
+
+ [ "aldenquimby.id", "aldeoryn.id",
+ "alderete.id", "aldert.id",
+ "aldi.id", "aldighieri.id", ... ]
+
+## Profile Search [GET /v1/search?query={query}]
+Searches for a profile using a search string.
++ Public Only Endpoint
++ Parameters
+ + query: wenger (string) - the search query
++ Response 200 (application/json)
+ + Body
+
+ [ "aldenquimby.id", "aldeoryn.id",
+ "alderete.id", "aldert.id",
+ "aldi.id", "aldighieri.id", ... ]
diff --git a/_core/.svn/pristine/c7/c77b412a33b9eef4154be22a12afc2b1276288a7.svn-base b/_core/.svn/pristine/c7/c77b412a33b9eef4154be22a12afc2b1276288a7.svn-base
new file mode 100644
index 00000000..bd1dc80e
--- /dev/null
+++ b/_core/.svn/pristine/c7/c77b412a33b9eef4154be22a12afc2b1276288a7.svn-base
@@ -0,0 +1,114 @@
+# Install Script
+
+We provide a [script](../images/scripts/ubuntu-17.04.sh) which will
+perform all the steps outlined in this doc (except for creating a protocol handler -- see the bottom of the doc). The script creates a virtualenv of
+Blockstack Core and installs Browser in a subdirectory. It additionally creates some
+scripts for starting Core and Browser together.
+
+However, if you'd like to customize your install, step through it
+yourself, or you are on a different distro, continue on with this doc!
+
+# Setting up Blockstack Core API Service
+
+Install required binaries in Ubuntu:
+
+```
+sudo apt update && sudo apt-get install -y python-pip python-dev libssl-dev libffi-dev rng-tools curl build-essential
+```
+
+
+If you'd like to use a virtualenv to install Blockstack, you can do that
+
+```
+pip install virtualenv
+virtualenv --python=python2.7 ~/.blockstack.venv/ && source ~/.blockstack.venv/bin/activate
+```
+
+Let's install virtualchain 0.14.3 and blockstack 0.14.3
+
+```
+sudo apt install git
+pip install git+https://github.com/blockstack/virtualchain.git@rc-0.14.3
+pip install git+https://github.com/blockstack/blockstack-core.git@rc-0.14.3
+```
+
+Get Blockstack core configured with default settings and choose your Bitcoin wallet password
+```
+blockstack setup -y --password BITCOIN_WALLET_PASSWORD --debug
+```
+
+# Setting up Blockstack Browser Node Application
+
+Install NodeJS through NodeSource PPA
+
+```
+curl -sL https://deb.nodesource.com/setup_7.x | sudo -E bash -
+sudo apt install -y nodejs
+```
+
+Download Blockstack Browser and install its dependencies
+
+```
+git clone https://github.com/blockstack/blockstack-browser.git -bv0.11.1
+cd blockstack-browser
+npm install node-sass
+npm install
+```
+
+Note that `blockstack-browser` depends on `node-sass` which can sometimes install strangely on Linux, running `npm install node-sass` before trying to install the other dependencies solves that problem.
+
+# Running Blockstack Browser
+
+Now we're ready to run our Core API service and start the Browser node app.
+
+First, start the Core API service.
+
+```
+blockstack api start -y --password BITCOIN_WALLET_PASSWORD --debug
+```
+
+Start the CORS proxy.
+
+```
+npm run dev-proxy &
+```
+
+Start the Node Application
+
+```
+npm run dev
+```
+
+Then you can open `http://localhost:3000/` in your browser to get to the Blockstack Browser.
+
+
+You can copy your api password to your clipboard with this command:
+```
+grep api_password ~/.blockstack/client.ini | sed 's/api_password = //g' | xclip -selection clipboard
+```
+
+## Setting up a protocol handler
+
+If you'd like your browser to automatically handle links with the `blockstack:` protocol specifier, you will need to register a protocol handler with your desktop environment. In Ubuntu/Gnome, this can be done by creating a file
+
+`~/.local/share/applications/blockstack.desktop`
+
+With the following contents:
+
+```
+[Desktop Entry]
+Type=Application
+Terminal=false
+Exec=bash -c 'xdg-open http://localhost:3000/auth?authRequest=$(echo "%u" | sed s,blockstack:////*,,)'
+Name=Blockstack-Browser
+MimeType=x-scheme-handler/blockstack;
+```
+
+Then you need to make this file executable, and register it as a protocol handler.
+
+```
+$ chmod +x ~/.local/share/applications/blockstack.desktop
+$ xdg-mime default blockstack.desktop x-scheme-handler/blockstack
+```
+
+Now, `blockstack:` protocol URLs should get handled by your Blockstack Browser. If you're running Browser in your browser's private mode, you may have to copy and paste the link, as this protocol handler will try to open in a regular browser window.
diff --git a/_core/.svn/pristine/c8/c87961a2649ca38e8ca60efe355e134470a8e794.svn-base b/_core/.svn/pristine/c8/c87961a2649ca38e8ca60efe355e134470a8e794.svn-base
new file mode 100644
index 00000000..d105df6c
--- /dev/null
+++ b/_core/.svn/pristine/c8/c87961a2649ca38e8ca60efe355e134470a8e794.svn-base
@@ -0,0 +1,223 @@
+/* eslint-env browser */
+/* eslint quotes: [2, "single"] */
+'use strict';
+
+/*
+ Determine if a string ends with another string.
+*/
+function endsWith(str, suffix) {
+ return str.indexOf(suffix, str.length - suffix.length) !== -1;
+}
+
+/*
+ Get a list of direct child elements by class name.
+*/
+function childrenByClass(element, name) {
+ var filtered = [];
+
+ for (var i = 0; i < element.children.length; i++) {
+ var child = element.children[i];
+ var classNames = child.className.split(' ');
+ if (classNames.indexOf(name) !== -1) {
+ filtered.push(child);
+ }
+ }
+
+ return filtered;
+}
+
+/*
+ Get an array [width, height] of the window.
+*/
+function getWindowDimensions() {
+ var w = window,
+ d = document,
+ e = d.documentElement,
+ g = d.body,
+ x = w.innerWidth || e.clientWidth || g.clientWidth,
+ y = w.innerHeight || e.clientHeight || g.clientHeight;
+
+ return [x, y];
+}
+
+/*
+ Collapse or show a request/response example.
+*/
+function toggleCollapseButton(event) {
+ var button = event.target.parentNode;
+ var content = button.parentNode.nextSibling;
+ var inner = content.children[0];
+
+ if (button.className.indexOf('collapse-button') === -1) {
+ // Clicked without hitting the right element?
+ return;
+ }
+
+ if (content.style.maxHeight && content.style.maxHeight !== '0px') {
+ // Currently showing, so let's hide it
+ button.className = 'collapse-button';
+ content.style.maxHeight = '0px';
+ } else {
+ // Currently hidden, so let's show it
+ button.className = 'collapse-button show';
+ content.style.maxHeight = inner.offsetHeight + 12 + 'px';
+ }
+}
+
+function toggleTabButton(event) {
+ var i, index;
+ var button = event.target;
+
+ // Get index of the current button.
+ var buttons = childrenByClass(button.parentNode, 'tab-button');
+ for (i = 0; i < buttons.length; i++) {
+ if (buttons[i] === button) {
+ index = i;
+ button.className = 'tab-button active';
+ } else {
+ buttons[i].className = 'tab-button';
+ }
+ }
+
+ // Hide other tabs and show this one.
+ var tabs = childrenByClass(button.parentNode.parentNode, 'tab');
+ for (i = 0; i < tabs.length; i++) {
+ if (i === index) {
+ tabs[i].style.display = 'block';
+ } else {
+ tabs[i].style.display = 'none';
+ }
+ }
+}
+
+/*
+ Collapse or show a navigation menu. It will not be hidden unless it
+ is currently selected or `force` has been passed.
+*/
+function toggleCollapseNav(event, force) {
+ var heading = event.target.parentNode;
+ var content = heading.nextSibling;
+ var inner = content.children[0];
+
+ if (heading.className.indexOf('heading') === -1) {
+ // Clicked without hitting the right element?
+ return;
+ }
+
+ if (content.style.maxHeight && content.style.maxHeight !== '0px') {
+ // Currently showing, so let's hide it, but only if this nav item
+ // is already selected. This prevents newly selected items from
+ // collapsing in an annoying fashion.
+ if (force || window.location.hash && endsWith(event.target.href, window.location.hash)) {
+ content.style.maxHeight = '0px';
+ }
+ } else {
+ // Currently hidden, so let's show it
+ content.style.maxHeight = inner.offsetHeight + 12 + 'px';
+ }
+}
+
+/*
+ Refresh the page after a live update from the server. This only
+ works in live preview mode (using the `--server` parameter).
+*/
+function refresh(body) {
+ document.querySelector('body').className = 'preload';
+ document.body.innerHTML = body;
+
+ // Re-initialize the page
+ init();
+ autoCollapse();
+
+ document.querySelector('body').className = '';
+}
+
+/*
+ Determine which navigation items should be auto-collapsed to show as many
+ as possible on the screen, based on the current window height. This also
+ collapses them.
+*/
+function autoCollapse() {
+ var windowHeight = getWindowDimensions()[1];
+ var itemsHeight = 64; /* Account for some padding */
+ var itemsArray = Array.prototype.slice.call(
+ document.querySelectorAll('nav .resource-group .heading'));
+
+ // Get the total height of the navigation items
+ itemsArray.forEach(function (item) {
+ itemsHeight += item.parentNode.offsetHeight;
+ });
+
+ // Should we auto-collapse any nav items? Try to find the smallest item
+ // that can be collapsed to show all items on the screen. If not possible,
+ // then collapse the largest item and do it again. First, sort the items
+ // by height from smallest to largest.
+ var sortedItems = itemsArray.sort(function (a, b) {
+ return a.parentNode.offsetHeight - b.parentNode.offsetHeight;
+ });
+
+ while (sortedItems.length && itemsHeight > windowHeight) {
+ for (var i = 0; i < sortedItems.length; i++) {
+ // Will collapsing this item help?
+ var itemHeight = sortedItems[i].nextSibling.offsetHeight;
+ if ((itemsHeight - itemHeight <= windowHeight) || i === sortedItems.length - 1) {
+ // It will, so let's collapse it, remove its content height from
+ // our total and then remove it from our list of candidates
+ // that can be collapsed.
+ itemsHeight -= itemHeight;
+ toggleCollapseNav({target: sortedItems[i].children[0]}, true);
+ sortedItems.splice(i, 1);
+ break;
+ }
+ }
+ }
+}
+
+/*
+ Initialize the interactive functionality of the page.
+*/
+function init() {
+ var i, j;
+
+ // Make collapse buttons clickable
+ var buttons = document.querySelectorAll('.collapse-button');
+ for (i = 0; i < buttons.length; i++) {
+ buttons[i].onclick = toggleCollapseButton;
+
+ // Show by default? Then toggle now.
+ if (buttons[i].className.indexOf('show') !== -1) {
+ toggleCollapseButton({target: buttons[i].children[0]});
+ }
+ }
+
+ var responseCodes = document.querySelectorAll('.example-names');
+ for (i = 0; i < responseCodes.length; i++) {
+ var tabButtons = childrenByClass(responseCodes[i], 'tab-button');
+ for (j = 0; j < tabButtons.length; j++) {
+ tabButtons[j].onclick = toggleTabButton;
+
+ // Show by default?
+ if (j === 0) {
+ toggleTabButton({target: tabButtons[j]});
+ }
+ }
+ }
+
+ // Make nav items clickable to collapse/expand their content.
+ var navItems = document.querySelectorAll('nav .resource-group .heading');
+ for (i = 0; i < navItems.length; i++) {
+ navItems[i].onclick = toggleCollapseNav;
+
+ // Show all by default
+ toggleCollapseNav({target: navItems[i].children[0]});
+ }
+}
+
+// Initial call to set up buttons
+init();
+
+window.onload = function () {
+ autoCollapse();
+ // Remove the `preload` class to enable animations
+ document.querySelector('body').className = '';
+};
diff --git a/_core/.svn/pristine/cc/cc2e623df0d9a7d3066b7a700e5d30f040d08eb6.svn-base b/_core/.svn/pristine/cc/cc2e623df0d9a7d3066b7a700e5d30f040d08eb6.svn-base
new file mode 100644
index 00000000..ecdb12ac
--- /dev/null
+++ b/_core/.svn/pristine/cc/cc2e623df0d9a7d3066b7a700e5d30f040d08eb6.svn-base
@@ -0,0 +1 @@
+The documentation has been moved to [docs.blockstack.org](https://docs.blockstack.org/), please update your bookmarks.
diff --git a/_core/.svn/pristine/ce/ceaf90da328eb3b692d4afd137e597c6a5e9a371.svn-base b/_core/.svn/pristine/ce/ceaf90da328eb3b692d4afd137e597c6a5e9a371.svn-base
new file mode 100644
index 00000000..6ad02a5b
Binary files /dev/null and b/_core/.svn/pristine/ce/ceaf90da328eb3b692d4afd137e597c6a5e9a371.svn-base differ
diff --git a/_core/.svn/pristine/d9/d9611b1f30c3d3cd5b5711313d6f5c9b49a283b5.svn-base b/_core/.svn/pristine/d9/d9611b1f30c3d3cd5b5711313d6f5c9b49a283b5.svn-base
new file mode 100644
index 00000000..d6c5ada3
--- /dev/null
+++ b/_core/.svn/pristine/d9/d9611b1f30c3d3cd5b5711313d6f5c9b49a283b5.svn-base
@@ -0,0 +1,314 @@
+---
+layout: core
+permalink: /:collection/:path.html
+---
+# Subdomain Design and Implementation
+
+{:.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:
+
+* TOC
+{:toc}
+
+
+## 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/`,
+`/v1/names/`, and `/v1/addresses/bitcoin/`)
+The endpoints which *are* subdomain aware are marked as such in
+[api-specs.md].
+
+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/`,
+`/v1/names/`, and `/v1/addresses/bitcoin/` 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](https://github.com/blockstack/blockstack-core/blob/master/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)
+```
diff --git a/_core/.svn/pristine/dc/dc7e58c79803a8d9f6dc84bc4b56e041d40ab470.svn-base b/_core/.svn/pristine/dc/dc7e58c79803a8d9f6dc84bc4b56e041d40ab470.svn-base
new file mode 100644
index 00000000..6fb9b3ed
--- /dev/null
+++ b/_core/.svn/pristine/dc/dc7e58c79803a8d9f6dc84bc4b56e041d40ab470.svn-base
@@ -0,0 +1,143 @@
+---
+layout: learn
+permalink: /:collection/:path.html
+---
+# Developer FAQs
+{:.no_toc}
+
+These FAQs are intended for developers of Blockstack.
+
+* TOC
+{:toc}
+
+
+## I'm a Web developer. Can I build on Blockstack?
+
+Yes! Blockstack is geared primarily towards Web developers. All of your
+existing knowledge is immediately applicable to Blockstack. Anything you can do
+in a Web browser, you can do in a Blockstack app.
+
+## I'm a non-Web developer. Can I build on Blockstack?
+
+Yes! Blockstack implements a [RESTful API](https://core.blockstack.org) which
+lets you interact with Blockstack from any language and any runtime. In fact,
+the reference client
+([blockstack.js](https://github.com/blockstack/blockstack.js)) is mainly a
+wrapper around these RESTful API calls, so you won't be missing much by using a
+language other than Javascript.
+
+## What's the difference between a Web app and a Blockstack app?
+
+Blockstack apps are built like [single-page Web
+apps](https://en.wikipedia.org/wiki/Single-page_application)---they are, in
+fact, a type of Web application.
+
+Blockstack apps are a subset of Web applications that use Blockstack's
+technology to preserve the user's control over their identities and data.
+As such, they tend to be simpler
+in design and operation, since in many cases they don't have to host anything
+besides the application's assets.
+
+## Do I need to learn any new languages or frameworks?
+
+No. Blockstack applications are built using existing Web frameworks and programming
+The only new thing you need to learn is either [blockstack.js](https://github.com/blockstack/blockstack.js) or
+the [Blockstack RESTful API](https://core.blockstack.org).
+
+## How does my Web app interact with Blockstack?
+
+The [blockstack.js](https://github.com/blockstack/blockstack.js) library gives
+any Web application the ability to interact with Blockstack's authentication and
+storage services. In addition, we supply a [public RESTful API](https://core.blockstack.org).
+
+## What does `blockstack.js` do?
+
+This is the reference client implementation for Blockstack. You use it in your
+Web app to do the following:
+
+* Authenticate users
+* Load and store user data
+* Read other users' public data
+
+## How do I use `blockstack.js`?
+
+Please see the API documentation [here](https://github.com/blockstack/blockstack.js).
+
+## How can I look up names and profiles?
+
+You can use `blockstack.js`, or you can use the [public Blockstack Core
+endpoint](https://core.blockstack.org).
+
+## How can I read my public app data without `blockstack.js`?
+
+The URLs to a user's public app data are in a canonical location in their
+profile. For example, here's how you would get public data from the
+[Publik](https://publik.ykliao.com) app, stored under the Blockstack ID `ryan.id`.
+
+1. Get the bucket URL
+```bash
+$ BUCKET_URL="$(curl -sL https://core.blockstack.org/v1/users/ryan.id | jq -r '."ryan.id"["profile"]["apps"]["http://publik.ykliao.com"]')"
+$ echo "$BUCKET_URL"
+https://gaia.blockstack.org/hub/1FrZTGQ8DM9TMPfGXtXMUvt2NNebLiSzad/
+```
+
+2. Get the data
+```bash
+$ curl -sL "${BUCKET_URL%%/}/statuses.json"
+[{"id":0,"text":"Hello, Blockstack!","created_at":1515786983492}]
+```
+
+## How do I register Blockstack IDs?
+
+You should use the [Blockstack Browser](https://github.com/blockstack/blockstack-browser).
+
+## How do I register Blockstack Subdomains?
+
+You can deploy and use a [Blockstack Subdomain Registrar]({{ site.baseurl }}/core/naming/subdomains.html), or
+use an existing one.
+
+## Can I programmatically register Blockstack IDs?
+
+Blockstack applications do not currently have
+have access to the user's wallet. Users are expected to
+register Blockstack IDs themselves.
+
+However, if you feel particularly ambitious, you can do one of the following:
+
+* Set up a `blockstack api` endpoint (see the project [README](https://github.com/blockstack/blockstack-core/blob/master/README.md)) and write a
+ program to automatically register names. Also, see the [API
+documentation](https://blockstack.github.io/blockstack-core/#managing-names-register-a-name)
+for registering names on this endpoint.
+
+* Write a `node.js` program that uses `blockstack.js` to register
+ names. This is currently in development.
+
+## Can I programmatically register Blockstack Subdomains?
+
+Yes! Once you deploy your own subdomain registrar, you can have your Web app
+send it requests to register subdomains on your Blockstack ID. You can also
+create a program that drives subdomain registration on your Blockstack ID.
+
+## Do you have a testnet or sandbox to experiment with Blockstack?
+
+We have an [integration test framework](https://github.com/blockstack/blockstack-core/tree/master/integration_tests) that provides a
+private Blockstack testnet. It uses `bitcoin -regtest` to create a private
+blockchain that you can interact with, without having to spend any Bitcoin or
+having to wait for blocks to confirm. Please see the
+[README](https://github.com/blockstack/blockstack-core/blob/master/integration_tests/README.md) for details.
+
+## Does Blockstack have a smart contract system?
+
+No, not yet. This is because
+Blockstack's design philosophy focuses on keeping system complexity at the
+"edges" of the network (e.g. clients), instead of the "core" of the network (e.g.
+the blockchain), in accordance with the [end-to-end
+principle](https://en.wikipedia.org/wiki/End-to-end_principle).
+Generally speaking, this can be interpreted as "if you can do X without
+a smart contract, you should do X without a smart contract." This organizing
+principle applies to a lot of useful decentralized applications.
+
+## Can Blockstack applications interact with Bitcoin? Ethereum? Smart contracts? Other blockchains?
+
+Yes! Since Blockstack applications are built like Web applications, all you need to do is include the
+relevant Javascript library into your application.
diff --git a/_core/.svn/pristine/e6/e62db085eeb3f020d661dee6738cd68f0a63fd77.svn-base b/_core/.svn/pristine/e6/e62db085eeb3f020d661dee6738cd68f0a63fd77.svn-base
new file mode 100644
index 00000000..b80a7dbe
--- /dev/null
+++ b/_core/.svn/pristine/e6/e62db085eeb3f020d661dee6738cd68f0a63fd77.svn-base
@@ -0,0 +1,127 @@
+---
+layout: core
+permalink: /:collection/:path.html
+---
+# How to Use the Atlas Network
+{:.no_toc}
+
+This section teaches you how to use the Atlas network, it contains the
+following sections:
+
+* TOC
+{:toc}
+
+## The API
+
+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.
+
+The [public BNS API endpoint](https://core.blockstack.org) 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
+[Blockstack Core](https://github.com/blockstack/blockstack-core) and use its
+Python client libraries for these examples.
+
+## Looking up Chunks
+
+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.
+
+A client can look up a chunk with the `get_zonefiles()` method. If successful,
+the returned payload will be a `dict` with a `zonefiles` key that maps the chunk
+hashes to their respective data.
+
+```python
+>>> import blockstack
+>>> data = blockstack.lib.client.get_zonefiles('https://node.blockstack.org:6263', ['1b89a685f4c4ea245ce9433d0b29166c22175ab4'])
+>>> print data['zonefiles']['1b89a685f4c4ea245ce9433d0b29166c22175ab4']
+$ORIGIN duckduckgo_tor.id
+$TTL 3600
+tor TXT "3g2upl4pq6kufc4m.onion"
+
+>>>
+```
+
+(This particular chunk happens to be associated with the BNS name
+`duckduckgo_tor.id`).
+
+## Adding a New Chunk
+
+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:
+
+* The name owner announces the chunk hash as a name's state
+via a `NAME_REGISTRATION`, `NAME_UPDATE`, `NAME_RENEWAL`, or `NAME_IMPORT` transaction.
+* Once the transaction is confirmed and processed by BNS, the name owner
+ broadcasts the matching zone file.
+
+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
+[blockstack.js](https://github.com/blockstack/blockstack.js) and the [Blockstack
+Browser](https://github.com/blockstack/blockstack-browser) for doing this.
+
+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:
+
+```python
+>>> import blockstack
+>>> import base64
+>>> data = "..." # this is the chunk data you will announce
+>>> data_b64 = base64.b64encode(data)
+>>> result = blockstack.lib.client.put_zonefiles('https://node.blockstack.org:6263', [data_b64])
+>>> assert result['saved'][0] == 1
+>>>
+```
+
+At most five chunks can be announced in one RPC call.
+Note that the data must be base64-encoded before it can be announced.
+
+When the `put_zonefiles()` method succeeds, it returns a `dict` with a list
+under the `saved` key. Here, `result['saved'][i]` will be 1 if the `i`th
+chunk given to `put_zonefiles()` 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.
+
+The `put_zonefiles()` method is idempotent.
+
+## Propagating Chunks
+
+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.
+
+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.
+
+For example, this code will replicate the chunk to not only
+`https://node.blockstack.org:6263`, but also to its immediate neighbors.
+
+```python
+>>> import blockstack
+>>> import base64
+>>> data = "..." # this is the chunk you will replicate widely
+>>> data_b64 = base64.b64encode(data)
+>>>
+>>> result = blockstack.lib.client.get_atlas_peers('https://node.blockstack.org:6263')
+>>> neighbors = result['peers']
+>>> print ", ".join(neighbors)
+13.65.207.163:6264, 52.225.128.191:6264, node.blockstack.org:6264, 23.102.162.7:6264, 52.167.230.235:6264, 23.102.162.124:6264, 52.151.59.26:6264, 13.92.134.106:6264
+>>>
+>>> for neighbor in neighbors:
+... result = blockstack.lib.client.put_zonefiles(neighbor, [data_b64])
+... assert result['saved'][0] == 1
+...
+>>>
+```
+
+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.
diff --git a/_core/.svn/pristine/e7/e7b15ecf76e943c691c7dcde44b0a454771a93a6.svn-base b/_core/.svn/pristine/e7/e7b15ecf76e943c691c7dcde44b0a454771a93a6.svn-base
new file mode 100644
index 00000000..80946f87
--- /dev/null
+++ b/_core/.svn/pristine/e7/e7b15ecf76e943c691c7dcde44b0a454771a93a6.svn-base
@@ -0,0 +1,88 @@
+---
+layout: core
+permalink: /:collection/:path.html
+---
+# Blockstack API
+{:.no_toc}
+* TOC
+{:toc}
+
+
+Step-by-step instructions for deploying a Blockstack API node on Debian or
+Ubuntu are below.
+
+- **Step 1:** Make sure you have Blockstack Core running locally (see [instructions](https://github.com/blockstack/blockstack-core/blob/master/README.md#quick-start)).
+
+- **Step 2:** Make sure you have [virtualenv installed](http://docs.python-guide.org/en/latest/dev/virtualenvs/).
+Then, setup the API:
+```
+$ sudo apt-get install -y python-pip memcached rng-tools python-dev libmemcached-dev zlib1g-dev libgmp-dev libffi-dev libssl-dev
+$ sudo service memcached start
+$ sudo pip install virtualenv
+$ sudo npm -g install aglio
+$ virtualenv api && source api/bin/activate
+$ git clone https://github.com/blockstack/blockstack-core.git
+$ cd blockstack-core/
+$ pip install .
+$ pip install -r api/requirements.txt
+$ blockstack setup_wallet
+$ blockstack api start
+$ deactivate
+$ ./build_docs.sh public_api
+```
+
+### Search Subsystem
+
+If you want to enable the search subsystem in your installation, you can
+follow the instructions [here](search.md).
+
+### Nginx Deployment
+
+For a production deployment we recommend using nginx and uwsgi:
+
+- **Step 1:** Install nginx and uWSGI:
+```
+$ sudo apt-get install -y nginx
+$ sudo pip install uwsgi
+```
+- **Step 2:** Copy [this sample nginx sites file](../api/nginx/config/nginx_sites-available/blockstack_api) to
+
+> /etc/nginx/sites-available/blockstack_api
+
+and edit the paths depending on the uwsgi blockstack_api socket directory (defaults to /tmp/blockstack_api.sock)
+You can test your nginx settings:
+```
+$ sudo nginx -t
+```
+- **Step 3:** Copy [this sample systemd service file](../api/nginx/config/systemd_system/blockstack_api.service) to
+
+> /etc/systemd/system/blockstack_api.service
+
+and edit the service user and blockstack paths depending on where your blockstack repo is located, and
+where your virtualenv is located.
+
+Note: The following sed commands will work if the virtualenv is currently active and your shell is in the repo's root directory.
+
+```
+$ sudo sed -i "s/User\=USER/User\=$USER/" /etc/systemd/system/blockstack_api.service
+$ sudo sed -i "s#/path/to/blockstack#$PWD#" /etc/systemd/system/blockstack_api.service
+$ sudo sed -i "s#/path/to/virtualenv#$VIRTUAL_ENV#" /etc/systemd/system/blockstack_api.service
+```
+
+- **Step 4:** Get a security certificate from [Let's Encrypt](https://letsencrypt.org/).
+```
+$ git clone https://github.com/certbot/certbot.git
+$ cd certbot/
+$ ./certbot-auto --nginx -d
+```
+
+And copy the cert files to the path given in the nginx sites file earlier.
+
+- **Step 5:** Start nginx and the Blockstack API uwsgi server:
+```
+sudo systemctl restart blockstack_api
+sudo systemctl restart nginx
+```
+
+If you run into any issues, please [submit a Github issue](https://github.com/blockstack/blockstack-core/issues) and we'll update these
+instructions.
diff --git a/_core/.svn/pristine/f0/f0326bcbb8f775c327237a64f0264c5df1763e5e.svn-base b/_core/.svn/pristine/f0/f0326bcbb8f775c327237a64f0264c5df1763e5e.svn-base
new file mode 100644
index 00000000..b5ae6b15
--- /dev/null
+++ b/_core/.svn/pristine/f0/f0326bcbb8f775c327237a64f0264c5df1763e5e.svn-base
@@ -0,0 +1,53 @@
+doctype
+
+
+include mixins.jade
+
+html
+ head
+ meta(charset="utf-8")
+ title= 'Blockstack Core'
+ link(rel="stylesheet", href="https://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css")
+ style!= self.css
+ body.preload
+ #nav-background
+ div.container-fluid.triple
+ .row
+ block nav
+ +Nav(true)
+
+ .content
+ #right-panel-background
+ .middle
+ header
+ h1#top!= 'Getting Started'
+ p!= 'Welcome to this deployment of Blockstack Core v{{server_info.server_version}}. You can read the documentation and make RESTful calls to this node.'
+ p
+ table
+ tr
+ td!= 'Consensus hash'
+ td!= '{{server_info.consensus}}'
+ tr
+
+ td!= 'Last block seen'
+ td!= '{{server_info.last_block_seen}}'
+ tr
+ td!= 'Last block processed'
+ td!= '{{server_info.last_block_processed}}'
+ p!= 'Blockstack Core is open-source software released under a GPLv3 license. The code for this API is available on Github and you can deploy your own nodes by following these instructions.'
+ block content
+ +ContentTriple(true)
+
+ .middle
+ p.text-muted(style="text-align: center;")
+
+ script: include scripts.js
+
+ if self.livePreview
+ script(src="/socket.io/socket.io.js")
+ script.
+ var socket = io();
+ socket.on('refresh', refresh);
+ socket.on('reconnect', function () {
+ socket.emit('request-refresh');
+ });
diff --git a/_core/.svn/pristine/f5/f5a4e6475e2847456f028230587b72ff55419f23.svn-base b/_core/.svn/pristine/f5/f5a4e6475e2847456f028230587b72ff55419f23.svn-base
new file mode 100644
index 00000000..5d75b35e
--- /dev/null
+++ b/_core/.svn/pristine/f5/f5a4e6475e2847456f028230587b72ff55419f23.svn-base
@@ -0,0 +1,124 @@
+# Advanced Usage
+
+This section details some of the advanced features in the CLI.
+
+## A Word of Warning
+
+Advanced features are meant to be used by experienced Blockstack users and developers, They receive less UI/UX testing than basic features, and their interfaces are expected to change to accomodate bugfixes and security fixes. Moreover, improper use of some advanced methods can cost you money, corrupt your profile, or compromise your wallet. Once they receive sufficient testing, an advanced feature may become a basic-mode feature in a subsequent release.
+
+**Do not use advanced mode unless you know what you are doing!**
+
+## Activating Advanced Mode
+
+To activate advanced mode, use the command `blockstack set_advanced_mode on`.
+
+To deactivate it later (recommended), use the command `blockstack set_advanced_mode off`.
+
+## Changing or Using Exiting Keys
+
+If you already have a payment key you want to use, or an owner key you want to migrate over, you can generate a wallet directly with `import_wallet`. We recommend using this command interactively, so you know which keys correspond to which usages.
+
+## Accounts
+
+With the accounts methods, you can directly manage your social proofs, link existing services to your profile, and store small bits of information.
+
+The account management methods are:
+* `get_account`: Look up an account in a name's profile. There can be more than one match.
+* `list_accounts`: List all accounts in a name's profile.
+* `put_account`: Add or update an account in a name's profile.
+* `delete_account`: Remove an account from a name's profile. This may need to be done more than once, if there are duplicates of the account.
+
+## Advanced Blockstack ID Queries
+
+Beyond `lookup` and `whois`, there are a few other more advanced queries you can run on Blockstack IDs. These include:
+
+### Listing Blockstack IDs
+* `get_all_names`: Get the list of every single Blockstack ID in existance.
+* `get_names_owned_by_address`: Get the list of names owned by a particular ownership address.
+
+### Querying the Blockchain
+* `get_name_blockchain_record`: Get the raw database record for a Blockstack ID. It will contain a *compressed* history of all name operations that have affected it. This is meant primarily for debugging purposes; to get an easier-to-parse listing of the information this command returns, use `get_name_blockchain_history`.
+* `get_name_blockchain_history`: Get the set of all prior states a Blockstack ID has been in, keyed by the block heights at which the state-change was processed.
+* `get_records_at`: Get the list of name operation records processed at a particular block height.
+* `list_update_history`: Get the list of all zonefile hashes that a Blockstack ID has ever had.
+
+### Zonefiles
+* `get_name_zonefile`: Get only a Blockstack ID's zonefile.
+* `list_zonefile_history`: Get the list of all zonefiles a Blockstack ID has ever had. **NOTE:** There is no guarantee that the server will hold copies of old zonefiles. This command is meant mainly for determining which historic zonefiles a server has processed.
+* `set_zonefile_hash`: This is the counterpart to `update`, but instead of setting the zonefile directly and uploading it to storage, you can use this command to directly set the data hash for a Blockstack ID. **NOTE:** You should ensure that the associated zonefile data has been replicated off-chain to a place where other users can get at it.
+
+### Lightweight Queries
+
+The lightweight lookup protocol for Blockstack is called *Simplified Name Verification* (SNV). This command returns a prior blockchain-level record given a more recent known-good consensus hash, serial number, or transaction ID of a transaction that contains a consensus hash. The CLI does not need to trust the Blockstack server to use these commands.
+
+* `lookup_snv`: Use the Merkle skip-list in the name database to look up a historic name operation on a Blockstack ID.
+
+## Consensus Queries
+
+You can query consensus hash information from the server with the following commands:
+
+* `consensus`: Get the consensus hash at a particular block height
+
+## Namespace Queries
+
+In addition to querying Blockstack IDs, the CLI has advanced commands for querying namespaces. These include:
+
+* `get_namespace_blockchain_record`: Get the raw database record for a Blockstack namespace. It will contain a *compressed* history of all namespace operations that have affected it.
+* `get_names_in_namespace`: Get the list of every Blockstack ID in a particular namespace.
+* `get_namespace_cost`: Get the cost required to preorder a namespace. Does *not* include the cost to reveal and ready it, nor does it include the transaction fees.
+
+## Namespace Creation
+
+**WARNING:** We do not recommend that you try to do this by yourself. Creating a namespace is **EXTREMELY EXPENSIVE**. If you are interested in creating your own namespace, please contact the Blockstack developers on the [Blockstack Slack](http://chat.blockstack.org).
+
+These methods allow you to create a namespace. There are three steps: preordering, revealing, and readying. Preordering a namespace is like preordering a name--you announce the hash of the namespace ID and the address that will control it. Revealing a namespace not only reveals the namespace ID, but also sets the pricing and lifetime rules for names in the namespace. After revealing the namespace, the namespace controller can pre-populate the namespace by importing Blockstack IDs. Once the namespace has been pre-populated, the controller sends a final transaction that readies the namespace for general use.
+
+* `namespace_preorder`: Preorder a namespace.
+* `namespace_reveal`: Reveal a namespace, and set its pricing and lifetime parameters. **NOTE:** This must be done within 144 blocks of sending the namespace preorder transaction.
+* `name_import`: Import a name into a revealed (but not readied) namespace. You can set its owner address and zonefile hash directly.
+* `namespace_ready`: Open a namespace for general registrations.
+
+## Data Storage
+
+Blockstack allows users to store arbitrary data to any set of storage providers for which the CLI has a driver. The data will be signed by the user's data key, so when other users read the data later on, they can verify that it is authentic (i.e. the storage provider is not trusted). Moreover, Blockstack is designed such that users don't have to know or care about which storage providers were used--as far as users can see, storage providers are just shared hard drives.
+
+There are two types of data supported by Blockstack: *mutable* data, and *immutable* data. Mutable data is linked by the profile, and can be written as fast and as frequently as the storage provider allows. Mutable data is addressed by URL.
+
+**WARNING:** While mutable data guarantees end-to-end authenticity, there is a chance that a malicious storage provider can serve new readers stale versions of the data. That is, users who have read the latest data already will not get tricked into reading stale data, but users who have *not yet* read the latest data *can* be tricked (i.e. the CLI keeps a version number for mutable data to do so). This must be taken into account if you intend to use this API.
+
+Immutable data, however, is content-addressed, and its cryptographic hash is stored to the user's zonefile. Writing immutable data will entail updating the zonefile and sending an `update` transaction (handled internally), so it will be slow by comparison. This has the advantage that storage providers cannot perform the aforementioned stale data attack, but has the downside that writes cost money and take a long time to complete.
+
+That said, we recommend using the mutable data API with several different storage providers whenever possible.
+
+### Mutable Data
+
+The following commands affect mutable data:
+
+* `get_mutable`: Use the profile to look up and fetch a piece of mutable data.
+* `put_mutable`: Add a link to mutable data to the profile, and replicate the signed data itself to all storage providers. Other users will need the data's name to read it with `get_mutable`.
+* `delete_mutable`: Remove a link to mutable data from the profile, and ask all storage providers to delete the signed data.
+
+### Immutable Data
+
+The following commnds affect immutable data:
+
+* `get_immutable`: Look up and fetch a piece of immutable data. You can supply either the name of the data, or its hash (both are stored in the zonefile, so there is no gain or loss of security in this choice).
+* `put_immutable`: Replicate a piece of data to all storage providers, add its name and hash to the zonefile, and issue an `update` to upload the new zonefile to Blockstack servers and write the hash to the blockchain.
+* `delete_immutable`: Remove the link to the data from the zonefile, ask all storage providers to delete the data, and issue an `update` to upload the new zonefile to Blockstack servers and write the new hash to the blockchain.
+* `list_immutable_data_history`: Given the name of a piece of immutable data, query the zonefile history to find the historic list of hashes it has had. **NOTE:** Like `list_zonefile_history` above, this only returns data hashes for the data if the Blockstack server has the historic zonefile.
+
+## Fault Recovery
+
+Sometimes, things beyond our control can happen. Transactions can get stuck, storage providers can go offline or corrupt data, and so on. These commands are meant to assist in recovering from these problems:
+
+* `set_profile`: Directly set a Blockstack ID's profile. All previous accounts, data links, etc. must be included in the new profile, since the old profile (if still present) will be overwritten by the one given here.
+* `convert_legacy_profile`: Given a legacy profile taken from a resolver, directly convert it into a new profile. This can be used with `set_profile` to recover from a failed profile migration.
+* `unqueue`: If a transaction gets lost or stuck, you can remove it from the CLI's transaction queue with this command. This will allow you to re-try it.
+* `rpcctl`: This lets you directly start or stop the Blockstack CLI's background daemon, which lets you recover from any crashes it experiences (you can find a trace of its behavior in `~/.blockstack/api_endpoint.log`)
+
+## Programmatic Access
+
+Other programs may want to make RPC calls the Blockstack CLI daemon. They can do so using either the `blockstack_client` Python package, or they can do so via the CLI as follows:
+
+* `rpc`: Issue a JSON RPC call. Takes a raw JSON string that encodes a list of arguments.
+
diff --git a/_core/.svn/pristine/f9/f9a32269948f7336ad81a20adb6854c26433adeb.svn-base b/_core/.svn/pristine/f9/f9a32269948f7336ad81a20adb6854c26433adeb.svn-base
new file mode 100644
index 00000000..46956d6b
--- /dev/null
+++ b/_core/.svn/pristine/f9/f9a32269948f7336ad81a20adb6854c26433adeb.svn-base
@@ -0,0 +1,99 @@
+---
+layout: core
+permalink: /:collection/:path.html
+---
+## Decentralized Identifiers (DIDs)
+
+BNS nodes are compliant with the emerging
+[Decentralized Identity Foundation](http://identity.foundation) protocol
+specification for decentralized identifiers (DIDs).
+
+Each name in BNS has an associated DID. The DID format for BNS is:
+
+```
+ did:stack:v0:{address}-{index}
+```
+
+Where:
+* `{address}` is an on-chain public key hash (e.g. a Bitcoin address).
+* `{index}` refers to the `nth` name this address created.
+
+For example, the DID for `personal.id` is
+`did:stack:v0:1dARRtzHPAFRNE7Yup2Md9w18XEQAtLiV-0`, because the name
+`personal.id` was the first-ever name created by
+`1dARRtzHPAFRNE7Yup2Md9w18XEQAtLiV`.
+
+As another example, the DID for `jude.id` is `did:stack:v0:16EMaNw3pkn3v6f2BgnSSs53zAKH4Q8YJg-1`.
+Here, the address `16EMaNw3pkn3v6f2BgnSSs53zAKH4Q8YJg` had created one earlier
+name in history prior to this one (which happens to be `abcdefgh123456.id`).
+
+The purpose of a DID is to provide an eternal identifier for a public key.
+The public key may change, but the DID will not.
+
+Blockstack Core implements a DID method of its own
+in order to be compatible with other systems that use DIDs for public key resolution.
+In order for a DID to be resolvable, all of the following must be true for a
+name:
+
+* The name must exist
+* The name's zone file hash must be the hash of a well-formed DNS zone file
+* The DNS zone file must be present in the BNS [Atlas Network]({{ site.baseurl }}/core/atlas/overview.html)
+* The DNS zone file must contain a `URI` resource record that points to a signed
+ JSON Web Token
+* The public key that signed the JSON Web Token (and is included with it) must
+ hash to the address that owns the name
+
+Not all names will have DIDs that resolve to public keys. However, names created by the [Blockstack
+Browser](https://github.com/blockstack/blockstack-browser) will have DIDs that
+do.
+
+Developers can programmatically resolve DIDs via the Python API:
+
+```Python
+>>> import blockstack
+>>> blockstack.lib.client.resolve_DID('did:stack:v0:16EMaNw3pkn3v6f2BgnSSs53zAKH4Q8YJg-1', hostport='https://node.blockstack.org:6263')
+{'public_key': '020fadbbcea0ff3b05f03195b41cd991d7a0af8bd38559943aec99cbdaf0b22cc8'}
+```
+
+A RESTful API is under development.
+
+
+# DID Encoding for Subdomains
+
+Every name and subdomain in BNS has a DID. The encoding is slightly different
+for subdomains, so the software can determine which code-path to take.
+
+* For on-chain BNS names, the `{address}` is the same as the Bitcoin address
+ that owns the name. Currently, both version byte 0 and version byte 5
+addresses are supported (i.e. addresses starting with `1` or `3`, meaning `p2pkh` and
+`p2sh` addresses).
+
+* For off-chain BNS subdomains, the `{address}` has version byte 63 for
+ subdomains owned by a single private key, and version byte 50 for subdomains
+owned by a m-of-n set of private keys. That is, subdomain DID addresses start
+with `S` or `M`, respectively.
+
+The `{index}` field for a subdomain's DID is distinct from the `{index}` field
+for a BNS name's DID, even if the same created both names and subdomains.
+For example, the name `abcdefgh123456.id` has the DID `did:stack:v0:16EMaNw3pkn3v6f2BgnSSs53zAKH4Q8YJg-0`,
+because it was the first name created by `16EMaNw3pkn3v6f2BgnSSs53zAKH4Q8YJg`.
+However, `16EMaNw3pkn3v6f2BgnSSs53zAKH4Q8YJg` *also* created `jude.statism.id`
+as its first subdomain name. The DID for `jude.statism.id` is
+`did:stack:v0:SSXMcDiCZ7yFSQSUj7mWzmDcdwYhq97p2i-0`. Note that the address
+`SSXMcDiCZ7yFSQSUj7mWzmDcdwYhq97p2i` encodes the same public key hash as the address
+`16EMaNw3pkn3v6f2BgnSSs53zAKH4Q8YJg` (the only difference between these two
+strings is that the first is base58check-encoded with version byte 0, and the
+second is encoded with version byte 63).
+
+You can see this play out in practice with the following code snippit:
+
+```python
+>>> import blockstack
+>>> blockstack.lib.client.get_name_record('jude.statism.id', hostport='https://node.blockstack.org:6263')['address']
+u'16EMaNw3pkn3v6f2BgnSSs53zAKH4Q8YJg'
+>>> import virtualchain
+>>> virtualchain.address_reencode('16EMaNw3pkn3v6f2BgnSSs53zAKH4Q8YJg', version_byte=63)
+'SSXMcDiCZ7yFSQSUj7mWzmDcdwYhq97p2i'
+>>> blockstack.lib.client.resolve_DID('did:stack:v0:SSXMcDiCZ7yFSQSUj7mWzmDcdwYhq97p2i-0', hostport='https://node.blockstack.org:6263')
+{'public_key': '020fadbbcea0ff3b05f03195b41cd991d7a0af8bd38559943aec99cbdaf0b22cc8'}
+```
diff --git a/_core/.svn/wc.db b/_core/.svn/wc.db
new file mode 100644
index 00000000..c58fee1c
Binary files /dev/null and b/_core/.svn/wc.db differ
diff --git a/_core/.svn/wc.db-journal b/_core/.svn/wc.db-journal
new file mode 100644
index 00000000..e69de29b
diff --git a/_core/README.md b/_core/README.md
new file mode 100644
index 00000000..a9c3abf6
--- /dev/null
+++ b/_core/README.md
@@ -0,0 +1,5 @@
+# About this `docs` directory
+
+The contents of this directory acts as source for material for
+[docs.blockstack.org](https://docs.blockstack.org/), a searchable documentation
+site for all things Blockstack.
diff --git a/_core/advanced_usage.md b/_core/advanced_usage.md
new file mode 100644
index 00000000..aadc8584
--- /dev/null
+++ b/_core/advanced_usage.md
@@ -0,0 +1,2 @@
+
+The documentation has been moved to [docs.blockstack.org](https://docs.blockstack.org/), please update your bookmarks.
diff --git a/_core/aglio_templates/core.jade b/_core/aglio_templates/core.jade
new file mode 100644
index 00000000..de87cfe9
--- /dev/null
+++ b/_core/aglio_templates/core.jade
@@ -0,0 +1,36 @@
+doctype
+
+include mixins.jade
+
+html
+ head
+ meta(charset="utf-8")
+ title= self.api.name || 'API Documentation'
+ link(rel="stylesheet", href="https://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css")
+ style!= self.css
+ body.preload
+ #nav-background
+ div.container-fluid.triple
+ .row
+ block nav
+ +Nav(false)
+
+ .content
+ #right-panel-background
+
+ block content
+ +ContentTriple(false)
+
+ .middle
+ p.text-muted(style="text-align: center;")
+
+ script: include scripts.js
+
+ if self.livePreview
+ script(src="/socket.io/socket.io.js")
+ script.
+ var socket = io();
+ socket.on('refresh', refresh);
+ socket.on('reconnect', function () {
+ socket.emit('request-refresh');
+ });
diff --git a/_core/aglio_templates/mixins.jade b/_core/aglio_templates/mixins.jade
new file mode 100644
index 00000000..ddc54690
--- /dev/null
+++ b/_core/aglio_templates/mixins.jade
@@ -0,0 +1,357 @@
+mixin TryMe(action)
+ //- Give a "try-me" link for the public api endpoint
+ - var myUri = action.uriTemplate
+ - action.parameters.forEach( function (x) { myUri = myUri.replace( "{" + x.name + "}", x.example) } )
+ .title
+ strong
+ h4
+ div
+ div
+ span.method(class="badge get",style="float:left")
+ a.method(href=myUri, style="color:rgb(51, 122, 183);font-size:12pt")
+ = "Try It!"
+ |
+ p
+ div
+ |
+
+mixin Badge(method)
+ //- Draw a badge for a given HTTP method
+ case method
+ when 'GET'
+ span.badge.get: i.fa.fa-arrow-down
+ when 'HEAD'
+ span.badge.head: i.fa.fa-info-circle
+ when 'OPTIONS'
+ span.badge.options: i.fa.fa-dot-circle-o
+ when 'POST'
+ span.badge.post: i.fa.fa-plus
+ when 'PUT'
+ span.badge.put: i.fa.fa-pencil
+ when 'PATCH'
+ span.badge.patch: i.fa.fa-pencil
+ when 'DELETE'
+ span.badge.delete: i.fa.fa-times
+ default
+ span.badge: i.fa.fa-dot-circle-o
+
+mixin Nav(onlyPublic)
+ //- Draw a navigation bar, which includes links to individual
+ //- resources and actions.
+ nav
+ if self.api.navItems && self.api.navItems.length
+ .resource-group
+ .heading
+ .chevron
+ i.open.fa.fa-angle-down
+ a(href='#top') Overview
+ .collapse-content
+ ul: each item in self.api.navItems
+ li
+ a(href=item[1])!= item[0]
+ - if (onlyPublic){
+ - myGroups = self.api.resourceGroups.filter( filter_public_resourcegroups )
+ - }else{
+ - myGroups = self.api.resourceGroups.filter( filter_core_resourcegroups )
+ - }
+ each resourceGroup in myGroups || []
+ .resource-group
+ .heading
+ .chevron
+ i.open.fa.fa-angle-down
+ a(href=resourceGroup.elementLink)!= resourceGroup.name || 'Resource Group'
+ .collapse-content
+ ul
+ each item in resourceGroup.navItems || []
+ li
+ a(href=item[1])!= item[0]
+ - if (onlyPublic){
+ - myResources = resourceGroup.resources.filter( filter_public_resources )
+ - }else{
+ - myResources = resourceGroup.resources.filter( filter_core_resources )
+ - }
+ each resource in myResources || []
+ li
+ - if (onlyPublic){
+ - myActions = resource.actions.filter( filter_public_actions )
+ - }else{
+ - myActions = resource.actions.filter( filter_core_actions )
+ - }
+ if !self.condenseNav || (myActions.length != 1)
+ a(href=resource.elementLink)!= resource.name || 'Resource'
+ ul: each action in myActions || []
+ li: a(href=resource.elementLink)
+ +Badge(action.method)
+ != action.name || action.method + ' ' + (action.attributes && action.attributes.uriTemplate || resource.uriTemplate)
+ else
+ - var action = myActions[0]
+ a(href=resource.elementLink)
+ +Badge(action.method)
+ != action.name || resource.name || action.method + ' ' + (action.attributes && action.attributes.uriTemplate || resource.uriTemplate)
+ //- Link to the API hostname, e.g. api.yourcompany.com
+ each meta in self.api.metadata || {}
+ if meta.name == 'HOST'
+ p(style="text-align: center; word-wrap: break-word;")
+ a(href=meta.value)= meta.value
+
+mixin Parameters(params)
+ //- Draw a definition list of parameter names, types, defaults,
+ //- examples and descriptions.
+ .title
+ strong URI Parameters
+ .collapse-button.show
+ span.close Hide
+ span.open Show
+ .collapse-content
+ dl.inner: each param in params || []
+ dt= self.urldec(param.name)
+ dd
+ code= param.type || 'string'
+ |
+ if param.required
+ span.required (required)
+ else
+ span (optional)
+ |
+ if param.default
+ span.text-info.default
+ strong Default:
+ span= param.default
+ |
+ if param.example
+ span.text-muted.example
+ strong Example:
+ span= param.example
+ != self.markdown(param.description)
+ if param.values.length
+ p.choices
+ strong Choices:
+ each value in param.values
+ code= self.urldec(value.value)
+ = ' '
+
+mixin RequestResponse(title, request, collapse)
+ .title
+ strong
+ = title
+ if request.name
+ |
+ code= request.name
+ if collapse && request.hasContent
+ .collapse-button
+ span.close Hide
+ span.open Show
+ +RequestResponseBody(request, collapse)
+
+mixin RequestResponseBody(request, collapse, showBlank)
+ if request.hasContent || showBlank
+ div(class=collapse ? 'collapse-content' : ''): .inner
+ if request.description
+ .description!= self.markdown(request.description)
+
+ if Object.keys(request.headers).length
+ h5 Headers
+ pre: code
+ each item, index in request.headers
+ != self.highlight(item.name + ': ' + item.value, 'http')
+ if index < request.headers.length - 1
+ br
+ div(style="height: 1px;")
+ if request.body
+ h5 Body
+ pre: code
+ != self.highlight(request.body, null, ['json', 'yaml', 'xml', 'javascript'])
+ div(style="height: 1px;")
+ if request.schema
+ h5 Schema
+ pre: code
+ != self.highlight(request.schema, null, ['json', 'yaml', 'xml'])
+ div(style="height: 1px;")
+ if !request.hasContent
+ .description.text-muted This response has no content.
+ div(style="height: 1px;")
+
+mixin Examples(resourceGroup, resource, action)
+ each example in action.examples
+ each request in example.requests
+ +RequestResponse('Request', request, true)
+ each response in example.responses
+ +RequestResponse('Response', response, true)
+
+mixin Content()
+ //- Page header and API description
+ header
+ h1#top!= self.api.name || 'API Documentation'
+
+ if self.api.descriptionHtml
+ != self.api.descriptionHtml
+
+ //- Loop through and display information about all the resource
+ //- groups, resources, and actions.
+ each resourceGroup in self.api.resourceGroups || []
+ section.resource-group(id=resourceGroup.elementId)
+ h2.group-heading
+ != resourceGroup.name || 'Resource Group'
+ = " "
+ a.permalink(href=resourceGroup.elementLink) ¶
+ if resourceGroup.descriptionHtml
+ != resourceGroup.descriptionHtml
+
+ each resource in resourceGroup.resources || []
+ .resource(id=resource.elementId)
+ h3.resource-heading
+ != resource.name || ((resource.actions[0] != null) && resource.actions[0].name) || 'Resource'
+ = " "
+ a.permalink(href=resource.elementLink) ¶
+ if resource.description
+ != self.markdown(resource.description)
+
+ each action in resource.actions || []
+ .action(class=action.methodLower, id=action.elementId)
+ h4.action-heading
+ .name!= action.name
+ a.method(class=action.methodLower, href=action.elementLink)
+ = action.method
+ code.uri= self.urldec(action.uriTemplate)
+ if action.description
+ != self.markdown(action.description)
+
+ h4 Example URI
+ .definition
+ span.method(class=action.methodLower)= action.method
+ |
+ span.uri
+ span.hostname= self.api.host
+ != action.colorizedUriTemplate
+
+ //- A list of sub-sections for parameters, requests
+ //- and responses.
+ if action.parameters.length
+ +Parameters(action.parameters)
+ if action.examples
+ +Examples(resourceGroup, resource, action)
+
+- function filter_public_actions(x){
+- return (x.description.includes('+ Public Endpoint') || x.description.includes('+ Public Only Endpoint'))
+- }
+- function filter_public_resources(x){
+- return (x.actions.filter( filter_public_actions ).length > 0)
+- }
+- function filter_public_resourcegroups(x){
+- return (x.resources.filter( filter_public_resources ).length > 0)
+- }
+- function filter_core_actions(x){
+- return !(x.description.includes('+ Public Only Endpoint'))
+- }
+- function filter_core_resources(x){
+- return (x.actions.filter( filter_core_actions ).length > 0)
+- }
+- function filter_core_resourcegroups(x){
+- return (x.resources.filter( filter_core_resources ).length > 0)
+- }
+
+mixin ContentTriple(onlyPublic, descriptionHtml)
+
+ .right
+ h5 API Endpoint
+ a(href=self.api.host)= self.api.host
+ .middle
+ if descriptionHtml
+ != descriptionHtml
+
+ //- Loop through and display information about all the resource
+ //- groups, resources, and actions.
+ - if (onlyPublic){
+ - myGroups = self.api.resourceGroups.filter( filter_public_resourcegroups )
+ - }else{
+ - myGroups = self.api.resourceGroups.filter( filter_core_resourcegroups )
+ - }
+ each resourceGroup in myGroups || []
+ .middle
+ section.resource-group(id=resourceGroup.elementId)
+ h2.group-heading
+ != resourceGroup.name || 'Resource Group'
+ = " "
+ a.permalink(href=resourceGroup.elementLink) ¶
+ if resourceGroup.descriptionHtml
+ != resourceGroup.descriptionHtml
+
+ - if (onlyPublic){
+ - myResources = resourceGroup.resources.filter( filter_public_resources )
+ - }else{
+ - myResources = resourceGroup.resources.filter( filter_core_resources )
+ - }
+ each resource in myResources || []
+ if resource.public != null
+ .middle
+ .resource(id=resource.elementId)
+ a.permalink(href=resource.elementLink)
+ h3.resource-heading
+ != resource.name || ((resource.actions[0] != null) && resource.actions[0].name) || 'Resource'
+ = " "
+ ¶
+ if resource.description
+ != self.markdown(resource.description)
+
+ - if (onlyPublic){
+ - myActions = resource.actions.filter( filter_public_actions )
+ - }else{
+ - myActions = resource.actions.filter( filter_core_actions )
+ - }
+ each action in myActions || []
+ if action.examples
+ .right
+ .definition
+ span.method(class=action.methodLower)= action.method
+ |
+ span.uri
+ span.hostname= self.api.host
+ != action.colorizedUriTemplate
+ .tabs
+ if action.hasRequest
+ .example-names
+ span Requests
+ - var requestCount = 0
+ each example in action.examples
+ each request in example.requests
+ - requestCount++
+ span.tab-button= request.name || 'example ' + requestCount
+ each example in action.examples
+ each request in example.requests
+ .tab
+ +RequestResponseBody(request, false, true)
+ .tabs
+ .example-names
+ span Responses
+ each response in example.responses
+ span.tab-button= response.name
+ each response in example.responses
+ .tab
+ +RequestResponseBody(response, false, true)
+ else
+ each example in action.examples
+ .tabs
+ .example-names
+ span Responses
+ each response in example.responses
+ span.tab-button= response.name
+ each response in example.responses
+ .tab
+ +RequestResponseBody(response, false, true)
+ .middle
+ .action(class=action.methodLower, id=action.elementId)
+ h4.action-heading
+ .name!= action.name
+ a.method(class=action.methodLower, href=action.elementLink)
+ = action.method
+ code.uri= self.urldec(action.uriTemplate)
+ if action.description
+ != self.markdown(action.description)
+
+ //- A list of sub-sections for parameters, requests
+ //- and responses.
+ if action.parameters.length
+ +Parameters(action.parameters)
+ if onlyPublic
+ +TryMe(action)
+ hr.split
diff --git a/_core/aglio_templates/public.jade b/_core/aglio_templates/public.jade
new file mode 100644
index 00000000..b5ae6b15
--- /dev/null
+++ b/_core/aglio_templates/public.jade
@@ -0,0 +1,53 @@
+doctype
+
+
+include mixins.jade
+
+html
+ head
+ meta(charset="utf-8")
+ title= 'Blockstack Core'
+ link(rel="stylesheet", href="https://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css")
+ style!= self.css
+ body.preload
+ #nav-background
+ div.container-fluid.triple
+ .row
+ block nav
+ +Nav(true)
+
+ .content
+ #right-panel-background
+ .middle
+ header
+ h1#top!= 'Getting Started'
+ p!= 'Welcome to this deployment of Blockstack Core v{{server_info.server_version}}. You can read the documentation and make RESTful calls to this node.'
+ p
+ table
+ tr
+ td!= 'Consensus hash'
+ td!= '{{server_info.consensus}}'
+ tr
+
+ td!= 'Last block seen'
+ td!= '{{server_info.last_block_seen}}'
+ tr
+ td!= 'Last block processed'
+ td!= '{{server_info.last_block_processed}}'
+ p!= 'Blockstack Core is open-source software released under a GPLv3 license. The code for this API is available on Github and you can deploy your own nodes by following these instructions.'
+ block content
+ +ContentTriple(true)
+
+ .middle
+ p.text-muted(style="text-align: center;")
+
+ script: include scripts.js
+
+ if self.livePreview
+ script(src="/socket.io/socket.io.js")
+ script.
+ var socket = io();
+ socket.on('refresh', refresh);
+ socket.on('reconnect', function () {
+ socket.emit('request-refresh');
+ });
diff --git a/_core/aglio_templates/scripts.js b/_core/aglio_templates/scripts.js
new file mode 100644
index 00000000..d105df6c
--- /dev/null
+++ b/_core/aglio_templates/scripts.js
@@ -0,0 +1,223 @@
+/* eslint-env browser */
+/* eslint quotes: [2, "single"] */
+'use strict';
+
+/*
+ Determine if a string ends with another string.
+*/
+function endsWith(str, suffix) {
+ return str.indexOf(suffix, str.length - suffix.length) !== -1;
+}
+
+/*
+ Get a list of direct child elements by class name.
+*/
+function childrenByClass(element, name) {
+ var filtered = [];
+
+ for (var i = 0; i < element.children.length; i++) {
+ var child = element.children[i];
+ var classNames = child.className.split(' ');
+ if (classNames.indexOf(name) !== -1) {
+ filtered.push(child);
+ }
+ }
+
+ return filtered;
+}
+
+/*
+ Get an array [width, height] of the window.
+*/
+function getWindowDimensions() {
+ var w = window,
+ d = document,
+ e = d.documentElement,
+ g = d.body,
+ x = w.innerWidth || e.clientWidth || g.clientWidth,
+ y = w.innerHeight || e.clientHeight || g.clientHeight;
+
+ return [x, y];
+}
+
+/*
+ Collapse or show a request/response example.
+*/
+function toggleCollapseButton(event) {
+ var button = event.target.parentNode;
+ var content = button.parentNode.nextSibling;
+ var inner = content.children[0];
+
+ if (button.className.indexOf('collapse-button') === -1) {
+ // Clicked without hitting the right element?
+ return;
+ }
+
+ if (content.style.maxHeight && content.style.maxHeight !== '0px') {
+ // Currently showing, so let's hide it
+ button.className = 'collapse-button';
+ content.style.maxHeight = '0px';
+ } else {
+ // Currently hidden, so let's show it
+ button.className = 'collapse-button show';
+ content.style.maxHeight = inner.offsetHeight + 12 + 'px';
+ }
+}
+
+function toggleTabButton(event) {
+ var i, index;
+ var button = event.target;
+
+ // Get index of the current button.
+ var buttons = childrenByClass(button.parentNode, 'tab-button');
+ for (i = 0; i < buttons.length; i++) {
+ if (buttons[i] === button) {
+ index = i;
+ button.className = 'tab-button active';
+ } else {
+ buttons[i].className = 'tab-button';
+ }
+ }
+
+ // Hide other tabs and show this one.
+ var tabs = childrenByClass(button.parentNode.parentNode, 'tab');
+ for (i = 0; i < tabs.length; i++) {
+ if (i === index) {
+ tabs[i].style.display = 'block';
+ } else {
+ tabs[i].style.display = 'none';
+ }
+ }
+}
+
+/*
+ Collapse or show a navigation menu. It will not be hidden unless it
+ is currently selected or `force` has been passed.
+*/
+function toggleCollapseNav(event, force) {
+ var heading = event.target.parentNode;
+ var content = heading.nextSibling;
+ var inner = content.children[0];
+
+ if (heading.className.indexOf('heading') === -1) {
+ // Clicked without hitting the right element?
+ return;
+ }
+
+ if (content.style.maxHeight && content.style.maxHeight !== '0px') {
+ // Currently showing, so let's hide it, but only if this nav item
+ // is already selected. This prevents newly selected items from
+ // collapsing in an annoying fashion.
+ if (force || window.location.hash && endsWith(event.target.href, window.location.hash)) {
+ content.style.maxHeight = '0px';
+ }
+ } else {
+ // Currently hidden, so let's show it
+ content.style.maxHeight = inner.offsetHeight + 12 + 'px';
+ }
+}
+
+/*
+ Refresh the page after a live update from the server. This only
+ works in live preview mode (using the `--server` parameter).
+*/
+function refresh(body) {
+ document.querySelector('body').className = 'preload';
+ document.body.innerHTML = body;
+
+ // Re-initialize the page
+ init();
+ autoCollapse();
+
+ document.querySelector('body').className = '';
+}
+
+/*
+ Determine which navigation items should be auto-collapsed to show as many
+ as possible on the screen, based on the current window height. This also
+ collapses them.
+*/
+function autoCollapse() {
+ var windowHeight = getWindowDimensions()[1];
+ var itemsHeight = 64; /* Account for some padding */
+ var itemsArray = Array.prototype.slice.call(
+ document.querySelectorAll('nav .resource-group .heading'));
+
+ // Get the total height of the navigation items
+ itemsArray.forEach(function (item) {
+ itemsHeight += item.parentNode.offsetHeight;
+ });
+
+ // Should we auto-collapse any nav items? Try to find the smallest item
+ // that can be collapsed to show all items on the screen. If not possible,
+ // then collapse the largest item and do it again. First, sort the items
+ // by height from smallest to largest.
+ var sortedItems = itemsArray.sort(function (a, b) {
+ return a.parentNode.offsetHeight - b.parentNode.offsetHeight;
+ });
+
+ while (sortedItems.length && itemsHeight > windowHeight) {
+ for (var i = 0; i < sortedItems.length; i++) {
+ // Will collapsing this item help?
+ var itemHeight = sortedItems[i].nextSibling.offsetHeight;
+ if ((itemsHeight - itemHeight <= windowHeight) || i === sortedItems.length - 1) {
+ // It will, so let's collapse it, remove its content height from
+ // our total and then remove it from our list of candidates
+ // that can be collapsed.
+ itemsHeight -= itemHeight;
+ toggleCollapseNav({target: sortedItems[i].children[0]}, true);
+ sortedItems.splice(i, 1);
+ break;
+ }
+ }
+ }
+}
+
+/*
+ Initialize the interactive functionality of the page.
+*/
+function init() {
+ var i, j;
+
+ // Make collapse buttons clickable
+ var buttons = document.querySelectorAll('.collapse-button');
+ for (i = 0; i < buttons.length; i++) {
+ buttons[i].onclick = toggleCollapseButton;
+
+ // Show by default? Then toggle now.
+ if (buttons[i].className.indexOf('show') !== -1) {
+ toggleCollapseButton({target: buttons[i].children[0]});
+ }
+ }
+
+ var responseCodes = document.querySelectorAll('.example-names');
+ for (i = 0; i < responseCodes.length; i++) {
+ var tabButtons = childrenByClass(responseCodes[i], 'tab-button');
+ for (j = 0; j < tabButtons.length; j++) {
+ tabButtons[j].onclick = toggleTabButton;
+
+ // Show by default?
+ if (j === 0) {
+ toggleTabButton({target: tabButtons[j]});
+ }
+ }
+ }
+
+ // Make nav items clickable to collapse/expand their content.
+ var navItems = document.querySelectorAll('nav .resource-group .heading');
+ for (i = 0; i < navItems.length; i++) {
+ navItems[i].onclick = toggleCollapseNav;
+
+ // Show all by default
+ toggleCollapseNav({target: navItems[i].children[0]});
+ }
+}
+
+// Initial call to set up buttons
+init();
+
+window.onload = function () {
+ autoCollapse();
+ // Remove the `preload` class to enable animations
+ document.querySelector('body').className = '';
+};
diff --git a/_core/api-specs.md b/_core/api-specs.md
new file mode 100644
index 00000000..a16c5d2a
--- /dev/null
+++ b/_core/api-specs.md
@@ -0,0 +1,1806 @@
+# Group Core Node Administration
+
+Blockstack Core's API module provides a set of API calls for interacting with
+the node's configuration. Most configuration state is in the [Blockstack
+Browser](https://github.com/blockstack/blockstack-browser). Client-side state
+is managed by [blockstack.js](https://github.com/blockstack/blockstack.js).
+
+## Ping the node [GET /v1/node/ping]
+
+Ping the Blockstack node to see if it's alive.
+
++ Public Endpoint
++ Response 200 (application/json)
+ + Body
+
+ {
+ "status": "alive",
+ "version": "###version###"
+ }
+ + Schema
+
+ {
+ "type": "object",
+ "properties": {
+ "status": {
+ "type": "string"
+ },
+ "version": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "status",
+ "version"
+ ]
+ }
+
+# Group Managing Names
+
+## Fetch zone file [GET /v1/names/{name}/zonefile]
+
+Fetch a user's raw zone file. This only works for RFC-compliant zone files.
+This method returns an error for names that have non-standard zone files.
+
++ Public Endpoint
++ Parameters
+ + name: bar.test (string) - fully-qualified name
++ Response 200 (application/json)
+ + Body
+
+ {
+ "zonefile": "$ORIGIN bar.test\n$TTL 3600\n_https._tcp URI 10 1 \"https://gaia.blockstack.org/hub/17Zijx61Sp7SbVfRTdETo7PhizJHYEUxbY/profile.json\"\n"
+ }
+
+ + Schema
+
+ {
+ 'anyOf': [
+ {
+ 'type': 'object',
+ 'properties': {
+ 'zonefile': {
+ 'type': 'string',
+ 'pattern': '.+',
+ },
+ },
+ {
+ 'type': 'object',
+ 'properties': {
+ 'error': {
+ 'type': 'string',
+ 'pattern': '.+',
+ },
+ },
+ ]
+ }
+
++ Response 400 (application/json)
+ + Body
+
+ { "error": "Invalid name or subdomain" }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'error': { 'type': 'string' },
+ },
+ }
+
++ Response 404 (application/json)
+ + Body
+
+ { "error": "No zone file for name" }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'error': { 'type': 'string' },
+ },
+ }
+
+# Group Name Querying
+
+This family of API endpoints deals with querying name information.
+
+## Get all names [GET /v1/names?page={page}]
+Fetch a list of all names known to the node.
++ Public Endpoint
++ Parameters
+ + page: 23 (number) - names are returned in pages of size 100,
+ so specify the page number.
++ Response 200 (application/json)
+ + Body
+
+ [ "aldenquimby.id", "aldeoryn.id",
+ "alderete.id", "aldert.id",
+ "aldi.id", "aldighieri.id", ... ]
+
+ + Schema
+
+ {
+ 'type': 'array',
+ 'items': {
+ 'type': 'string',
+ 'pattern': '^([a-z0-9\\-_.+]{3,37})$',
+ }
+ }
+
++ Response 400 (application/json)
+ + Body
+
+ { "error": "Invalid page" }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'error': { 'type': 'string' },
+ },
+ }
+
+
+## Get all subdomains [GET /v1/subdomains?page={page}]
+Fetch a list of all names known to the node.
++ Public Endpoint
++ Parameters
+ + page: 3 (number) - names are returned in pages of size 100,
+ so specify the page number.
++ Response 200 (application/json)
+ + Body
+
+ [ ...
+ "collegeinfogeek.verified.podcast",
+ "collider.verified.podcast",
+ "combatandclassics.verified.podcast",
+ "combatjack.verified.podcast",
+ "comedybangbang.verified.podcast",
+ "comedybutton.verified.podcast",
+ "commonsense.verified.podcast",
+ "concilio002.personal.id", ... ]
+
+ + Schema
+
+ {
+ 'type': 'array',
+ 'items': {
+ 'type': 'string',
+ 'pattern': '^([a-z0-9\\-_.+]{3,37})\.([a-z0-9\\-_.+]{3,37})$',
+ }
+ }
+
++ Response 400 (application/json)
+ + Body
+
+ { "error": "Invalid page" }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'error': { 'type': 'string' },
+ },
+ }
+
+## Get name info [GET /v1/names/{name}]
++ Public Endpoint
++ Subdomain Aware
++ Parameters
+ + name: muneeb.id (string) - fully-qualified name
++ Response 200 (application/json)
+ + Body
+
+ {
+ "address": "1J3PUxY5uDShUnHRrMyU6yKtoHEUPhKULs",
+ "blockchain": "bitcoin",
+ "expire_block": 599266,
+ "grace_period": false,
+ "last_txid": "1edfa419f7b83f33e00830bc9409210da6c6d1db60f99eda10c835aa339cad6b",
+ "renewal_deadline": 604266,
+ "resolver": null,
+ "status": "registered",
+ "zonefile": "$ORIGIN muneeb.id\n$TTL 3600\n_http._tcp IN URI 10 1 \"https://gaia.blockstack.org/hub/1J3PUxY5uDShUnHRrMyU6yKtoHEUPhKULs/0/profile.json\"\n",
+ "zonefile_hash": "37aecf837c6ae9bdc9dbd98a268f263dacd00361"
+ }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'address': {
+ 'type': 'string',
+ 'pattern': "^([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]+)$",
+ },
+ 'blockchain': {
+ 'type': 'string',
+ 'pattern': '^bitcoin$',
+ },
+ 'expire_block': {
+ 'type': 'integer',
+ 'minimum': 0,
+ },
+ 'grace_period': {
+ 'type': 'integer',
+ 'minimum': 0,
+ },
+ 'last_txid': {
+ 'type': 'string',
+ 'pattern': '^[0-9a-fA-F]+$',
+ },
+ 'resolver': {
+ 'type': 'string',
+ },
+ 'status': {
+ 'type': 'string',
+ 'pattern': '^(registered|revoked)$',
+ },
+ 'zonefile': {
+ 'anyOf': [
+ {
+ 'type': 'string',
+ },
+ {
+ 'type': 'object',
+ 'properties': {
+ 'error': {
+ 'type': 'string',
+ },
+ },
+ },
+ ],
+ },
+ 'zonefile_hash': {
+ 'type': 'string',
+ 'pattern': '^[0-9a-fA-F]{20}$`,
+ },
+ },
+ { 'required':
+ [
+ 'address', 'blockchain', 'last_txid',
+ 'status', 'zonefile', 'zonefile_hash'
+ ]
+ }
+ }
+
++ Response 400 (application/json)
+ + Body
+
+ { "error": "Invalid name or subdomain" }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'error': { 'type': 'string' },
+ },
+ }
+
++ Response 404 (application/json)
+ + Body
+
+ { "error": "No such name" }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'error': { 'type': 'string' },
+ },
+ }
+
+## Get name history [GET /v1/names/{name}/history?page={page}]
+Get a history of all blockchain records of a registered name.
++ Public Endpoint
++ Subdomain aware
++ Parameters
+ + name: muneeb.id (string) - name to query
+ + page: 0 (integer) - the page (in 20-entry pages) of the history to fetch
++ Response 200 (application/json)
+ + Body
+
+ {
+ "373821": [
+ {
+ "address": "1QJQxDas5JhdiXhEbNS14iNjr8auFT96GP",
+ "block_number": 373821,
+ "consensus_hash": null,
+ "first_registered": 373821,
+ "importer": "76a9143e2b5fdd12db7580fb4d3434b31d4fe9124bd9f088ac",
+ "importer_address": "16firc3qZU97D1pWkyL6ZYwPX5UVnWc82V",
+ "last_creation_op": ";",
+ "last_renewed": 373821,
+ "name": "muneeb.id",
+ "name_hash128": "deb7fe99776122b77925cbf0a24ab6f8",
+ "namespace_block_number": 373601,
+ "namespace_id": "id",
+ "op": ";",
+ "op_fee": 100000.0,
+ "opcode": "NAME_IMPORT",
+ "preorder_block_number": 373821,
+ }
+ ]
+ }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'patternProperties': {
+ '^[0-9]+': {
+ 'type': 'array',
+ 'items': {
+ 'type': 'object',
+ 'properties': {
+ 'address': {
+ 'type': 'string',
+ 'pattern': "^([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]+)$",
+ },
+ 'base': {
+ 'type': 'integer',
+ 'minimum': 0,
+ 'maximum': 255,
+ },
+ 'buckets': {
+ 'anyOf': [
+ {
+ 'type': 'array',
+ 'items': {
+ 'type': 'integer',
+ 'minItems': 16,
+ 'maxItems': 16,
+ },
+ },
+ {
+ 'type': 'null',
+ },
+ ],
+ },
+ 'block_number': {
+ 'type': 'integer',
+ 'minimum': 0,
+ },
+ 'coeff': {
+ 'anyOf': [
+ {
+ 'type': 'integer',
+ 'minimum': 0,
+ 'maximum': 255,
+ },
+ {
+ 'type': 'null'
+ },
+ ],
+ },
+ 'consensus_hash': {
+ 'anyOf': [
+ {
+ 'type': 'string',
+ 'pattern': '^[0-9a-fA-F]{32}',
+ },
+ {
+ 'type': 'null'
+ },
+ ],
+ },
+ 'domain': {
+ 'type': 'string',
+ 'pattern': '^([a-z0-9\\-_.+]{3,37})$',
+ },
+ 'fee': {
+ 'type': 'integer',
+ 'minimum': 0,
+ },
+ 'first_registered': {
+ 'type': 'integer',
+ 'minimum': 0,
+ },
+ 'history_snapshot': {
+ 'type': 'boolean',
+ },
+ 'importer': {
+ 'anyOf': [
+ {
+ 'type': 'string',
+ 'pattern': '^76[aA]914[0-9a-fA-F]{40}88[aA][cC]$',
+ },
+ {
+ 'type': 'null',
+ },
+ ],
+ },
+ 'importer_address': {
+ 'anyOf': [
+ {
+ 'type': 'string',
+ 'pattern': "^([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]+)$",
+ },
+ {
+ 'type': 'null',
+ },
+ ],
+ },
+ 'last_renewed': {
+ 'type': 'integer',
+ 'minimum': 0,
+ },
+ 'name': {
+ 'type': 'string',
+ 'pattern': '^([a-z0-9\\-_.+]{3,37})\.([a-z0-9\\-_.+]{3,37})$',
+ },
+ 'op': {
+ 'type': 'string',
+ 'pattern': '^([>?+~:!&*:;#]{1}|>>|>~|::)$',
+ },
+ 'op_fee': {
+ 'type': 'number',
+ },
+ 'opcode': {
+ 'type': 'string',
+ 'pattern': '^NAME_TRANSFER|NAME_PREORDER|NAME_UPDATE|NAME_REVOKE|NAME_REGISTRATION|NAMESPACE_READY|NAMESPACE_REVEAL|NAMESPACE_PREORDER|NAME_RENEWAL|NAME_IMPORT|ANNOUNCE$'
+ },
+ 'revoked': {
+ 'type': 'boolean',
+ },
+ 'sender': {
+ 'type': 'string',
+ 'pattern': '^([0-9a-fA-F]+)$',
+ },
+ 'sender_pubkey': {
+ 'anyOf': [
+ {
+ 'type': 'string',
+ 'pattern': '^([0-9a-fA-F]+)$',
+ },
+ {
+ 'type': 'null'
+ },
+ ],
+ },
+ 'sequence': {
+ 'type': 'integer',
+ 'minimum': 0
+ }
+ 'recipient': {
+ 'anyOf': [
+ {
+ 'type': 'string',
+ 'pattern': '^([0-9a-fA-F]+)$',
+ },
+ {
+ 'type': 'null'
+ },
+ ],
+ },
+ 'recipient_address': {
+ 'anyOf': [
+ {
+ 'type': 'string',
+ 'pattern': '^([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]+)$',
+ },
+ {
+ 'type': 'null'
+ },
+ ],
+ },
+ 'recipient_pubkey': {
+ 'anyOf': [
+ {
+ 'type': 'string',
+ 'pattern': '^([0-9a-fA-F]+)$',
+ },
+ {
+ 'type': 'null'
+ },
+ ],
+ },
+ 'txid': {
+ 'type': 'string',
+ 'pattern': '^([0-9a-fA-F]+)$',
+ },
+ 'value_hash': {
+ 'anyOf': [
+ {
+ 'type': 'string',
+ 'pattern': '^([0-9a-fA-F]{40})$',
+ },
+ {
+ 'type': 'null',
+ },
+ ],
+ },
+ 'vtxindex': {
+ 'type': 'integer',
+ 'minimum': 0,
+ },
+ },
+ 'required': [
+ 'txid',
+ 'vtxindex'
+ ],
+ }
+ }
+ }
+ }
+
++ Response 400 (application/json)
+ + Body
+
+ { "error": "Invalid page" }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'error': { 'type': 'string' },
+ },
+ }
+
++ Response 404 (application/json)
+ + Body
+
+ { "error": "No such name" }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'error': { 'type': 'string' },
+ },
+ }
+
+## Get historical zone file [GET /v1/names/{name}/zonefile/{zoneFileHash}]
+Fetches the historical zonefile specified by the username and zone hash.
++ Public Endpoint
++ Subdomain aware
++ Parameters
+ + name: muneeb.id (string) username to fetch
+ + zoneFileHash: b100a68235244b012854a95f9114695679002af9
++ Response 200 (application/json)
+ + Body
+
+ {
+ "zonefile": "$ORIGIN muneeb.id\n$TTL 3600\n_http._tcp IN URI 10 1 \"https://blockstack.s3.amazonaws.com/muneeb.id\"\n"
+ }
+
+ + Schema
+
+ {
+ 'anyOf': [
+ {
+ 'type': 'object',
+ 'properties': {
+ 'zonefile': { 'type': 'string' },
+ },
+ },
+ {
+ 'type': 'object',
+ 'properties': {
+ 'error': { 'type': 'string' },
+ },
+ },
+ ],
+ }
+
++ Response 400 (application/json)
+ + Body
+
+ { "error": "Invalid name or subdomain" }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'error': { 'type': 'string' },
+ },
+ }
+
++ Response 404 (application/json)
+ + Body
+
+ { "error": "No such zonefile" }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'error': { 'type': 'string' },
+ },
+ }
+
+## Get names owned by address [GET /v1/addresses/{blockchain}/{address}]
+Retrieves a list of names owned by the address provided.
++ Subdomain Aware
++ Public Endpoint
++ Parameters
+ + blockchain: bitcoin (string) - the layer-1 blockchain for the address
+ + address: 1QJQxDas5JhdiXhEbNS14iNjr8auFT96GP (string) - the address to lookup
+
++ Response 200 (application/json)
+ + Body
+
+ {
+ "names": ["muneeb.id"]
+ }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'names': {
+ 'type': 'array',
+ 'items': {
+ 'type': 'string',
+ 'pattern': '^([a-z0-9\-_.+]{3,37})$',
+ }
+ }
+ }
+ }
+
++ Response 404 (application/json)
+ + Body
+
+ { "error": "Unsupported blockchain" }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'error': { 'type': 'string' },
+ },
+ }
+
+# Group Price Checks
+
+## Get namespace price [GET /v1/prices/namespaces/{tld}]
+
+This endpoint is used to get the price of a namespace.
+
++ Public Endpoint
++ Parameters
+ + tld: id (string) - namespace to query price for
++ Response 200 (application/json)
+ + Body
+
+ {
+ "satoshis": 4000000000,
+ "units": "BTC",
+ "amount": "4000000000"
+ }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'units': {
+ 'type': 'string',
+ },
+ 'amount': {
+ 'type': 'string',
+ 'pattern': '^[0-9]+$',
+ },
+ 'satoshis': {
+ 'type': 'integer',
+ 'minimum': 0,
+ },
+ },
+ 'required': [ 'satoshis' ]
+ }
+
++ Response 400 (application/json)
+ + Body
+
+ { "error": "Invalid namepace" }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'error': { 'type': 'string' },
+ },
+ }
+
+## Get name price [GET /v1/prices/names/{name}]
+
+This endpoint is used to get the price of a name. If you are using a public
+endpoint, you should *only* rely on the `name_price` field in the returned JSON
+blob.
+
+The other fields are relevant only for estimating the cost of registering a
+name. You register a name via
+[blockstack.js](https://github.com/blockstack/blockstack.js) or the [Blockstack
+Browser](https://github.com/blockstack/blockstack-browser)).
+
++ Public Endpoint
++ Parameters
+ + name: muneeb.id (string) - name to query price information for
++ Response 200 (application/json)
+ + Body
+
+ {
+ "name_price": {
+ "satoshis": 100000,
+ "units": "BTC",
+ "amount": "100000"
+ },
+ }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'name_price': {
+ 'type': 'object',
+ 'properties': {
+ 'satoshis': { 'type': 'integer', 'minimum': 0 },
+ 'units': { 'type': 'string' },
+ 'amount': { 'type': 'string', 'pattern': '^[0-9]+$' }
+ },
+ 'required': [ 'satoshis' ],
+ },
+ 'required': [ 'name_price' ]
+ }
+ }
+
++ Response 400 (application/json)
+ + Body
+
+ { "error": "Invalid name" }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'error': { 'type': 'string' },
+ },
+ }
+
+## Get namespace price [GET /v2/prices/namespaces/{tld}]
+
+This endpoint is used to get the price of a namespace, while explicitly
+indicating the cryptocurrency units. This is because going forward, namespaces
+are not necessarily priced in Bitcoin.
+
++ Public Endpoint
++ Parameters
+ + tld: id (string) - namespace to query price for
++ Response 200 (application/json)
+ + Body
+
+ {
+ "units": "BTC",
+ "amount": "4000000000"
+ }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'units': {
+ 'type': 'string',
+ },
+ 'amount': {
+ 'type': 'string',
+ 'pattern': '^[0-9]+$',
+ },
+ },
+ 'required': [ 'units', 'amount' ]
+ }
+
++ Response 400 (application/json)
+ + Body
+
+ { "error": "Invalid namespace" }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'error': { 'type': 'string' },
+ },
+ },
+
+## Get name price [GET /v2/prices/names/{name}]
+
+This endpoint is used to get the price of a name, denoted in a specific
+cryptocurrency (not necessarily Bitcoin).
+
++ Public Endpoint
++ Parameters
+ + name: muneeb.id (string) - name to query price information for
++ Response 200 (application/json)
+ + Body
+
+ {
+ "name_price": {
+ "units": "BTC",
+ "amount": "100000"
+ },
+ }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'name_price': {
+ 'type': 'object',
+ 'properties': {
+ 'units': { 'type': 'string' },
+ 'amount': { 'type': 'string', 'pattern': '^[0-9]+$' }
+ },
+ 'required': [ 'units', 'amount' ],
+ },
+ 'required': [ 'name_price' ]
+ }
+ }
+
++ Response 400 (application/json)
+ + Body
+
+ { "error": "Invalid name" }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'error': { 'type': 'string' },
+ },
+ },
+
+# Group Blockchain Operations
+
+## Get consensus hash [GET /v1/blockchains/{blockchainName}/consensus]
+
+Get the current Blockstack consensus hash on a blockchain.
++ Public Endpoint
++ Parameters
+ + blockchainName : bitcoin (string) - the given blockchain
++ Response 200 (application/json)
+ + Body
+
+ {
+ "consensus_hash": "2fcbdf66c350894fe03b42c6a2e8a6ac"
+ }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'consensus_hash': {
+ 'type': 'string',
+ 'pattern': '^[0-9a-fA-F]{32}$`,
+ },
+ },
+ }
+
++ Response 404 (application/json)
+ + Body
+
+ { "error": "Unsupported blockchain" }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'error': { 'type': 'string' },
+ },
+ }
+
+## Get total names on blockchain [GET /v1/blockchains/{blockchainName}/name_count{?all}]
+
+Get a count of the number of names on a blockchain. This does not include
+subdomains.
++ Public Endpoint
++ Parameters
+ + blockchainName: bitcoin (string) - the given blockchain
+ + all: true (enum[string], optional) - include expired names
++ Response 200 (application/json)
+ + Body
+
+ {
+ "names_count": 73950
+ }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'names_count': {
+ 'type': 'integer',
+ 'minimum': 0,
+ },
+ },
+ }
+
++ Response 404 (application/json)
+ + Body
+
+ { "error": "Unsupported blockchain" }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'error': { 'type': 'string' },
+ },
+ },
+
+
+## Get total subdomains on blockchain [GET /v1/blockchains/{blockchainName}/subdomains_count]
+Get the number of subdomains on a blockchain.
++ Public Endpoint
++ Parameters
+ + blockchainName: bitcoin (string) - the given blockchain
++ Response 200 (application/json)
+ + Body
+
+ {
+ "names_count": 1646
+ }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'names_count': {
+ 'type': 'integer',
+ 'minimum': 0,
+ },
+ },
+ }
+
++ Response 404 (application/json)
+ + Body
+
+ { "error": "Unsupported blockchain" }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'error': { 'type': 'string' },
+ },
+ },
+
+
+## Get operations in block [GET /v1/blockchains/{blockchainName}/operations/{blockHeight}]
+
+Get the Blockstack operations in a given block
++ Public Endpoint
++ Parameters
+ + blockchainName : bitcoin (string) - the given blockchain
+ + blockHeight : 462592 (integer) - the block height
++ Response 200 (application/json)
+ + Body
+
+ [
+ {
+ "address": "1GS1eHthSK2gqnU9MW9Nis1pUyHP3bJnFK",
+ "block_number": 462592,
+ "burn_address": "1111111111111111111114oLvT2",
+ "consensus_hash": "d206b2f615de00803402cade4d0d51d4",
+ "op": "?",
+ "op_fee": 6250,
+ "opcode": "NAME_PREORDER",
+ "preorder_hash": "ba22cdf24b05b9a7972e13ada69f96a7850b471e",
+ "sender": "76a914a944d29012f83c00105778e0bc717c46ea2accfc88ac",
+ "sender_pubkey": "0343b263f7adc6ae59e8d8310f4a6a87799f6b10cec608f3236cd6a802ffc71728",
+ "txid": "b3f4f7a43d60666d1a9b42131f9117ad7deac34a478b6ca152344da3d734691f",
+ "vtxindex": 173
+ },
+ {
+ "address": "1gijbF8NkbgwzcoZR1nXMa76NbdcD7GQW",
+ "block_number": 462592,
+ "burn_address": "1111111111111111111114oLvT2",
+ "consensus_hash": "d206b2f615de00803402cade4d0d51d4",
+ "op": "?",
+ "op_fee": 6250,
+ "opcode": "NAME_PREORDER",
+ "preorder_hash": "386e2de88a908ad056361e586faa95852be454ca",
+ "sender": "76a91407830f81167f6a2aa253c0f176b7ff2e1c04c61a88ac",
+ "sender_pubkey": "03b7795d33b362338179e5b2a579431b285f6c303d07ddd83c897277be4e5eb916",
+ "txid": "4dd315ad1d1b318614a19e15e767efb7ef327bd5cd4ebaf8f80ede58fd1da107",
+ "vtxindex": 174
+ },
+ {
+ "address": "17QEd6rrhNZp4xoyWu6BpA8NQ4axyNKaZy",
+ "block_number": 462592,
+ "burn_address": "1111111111111111111114oLvT2",
+ "consensus_hash": "d206b2f615de00803402cade4d0d51d4",
+ "op": "?",
+ "op_fee": 6250,
+ "opcode": "NAME_PREORDER",
+ "preorder_hash": "a7a388a2bbe0e7741c6cfdc54d7b5a67811cd582",
+ "sender": "76a9144635b1794a22bfbe6c5c5eba17b693f4aaf0e34888ac",
+ "sender_pubkey": "020d6e50b2660af27933c42bc1395fe93df90ffac5e2a989f6a134919fb8cf8075",
+ "txid": "51d6bd117da5889e710c62967d03233a84fc27f7fad10ca4359111928818f017",
+ "vtxindex": 332
+ },
+ {
+ "address": "15YMyvqz6v9ATSbmqJnudwrdm7RiVfkU3s",
+ "block_number": 462453,
+ "consensus_hash": "f6491e1d2b9817fa58512fc9bf8cd3df",
+ "first_registered": 462575,
+ "importer": null,
+ "importer_address": null,
+ "keep_data": true,
+ "last_renewed": 462575,
+ "name": "ablankstein.id",
+ "name_hash128": "943b8e0613d975c05a05ccd5472e2a72",
+ "namespace_block_number": 373601,
+ "namespace_id": "id",
+ "op": ">>",
+ "op_fee": 25000,
+ "opcode": "NAME_TRANSFER",
+ "preorder_block_number": 462453,
+ "preorder_hash": "822d5cb6f2e3f0f901d6af8c1111ee466b6c07bd",
+ "revoked": false,
+ "sender": "76a91431cee995f242f0f66518080a291714cd7e8d2f5e88ac",
+ "sender_pubkey": null,
+ "txid": "121540e81223c45d139fbe03a9713ddd292372f2f88fe2b10b6a7c5e6738e87f",
+ "value_hash": "96ec93cbc57d17b16a347c11ddfa7ea88d2cf93b",
+ "vtxindex": 633
+ },
+ {
+ "address": "1Dwq9oA5BNz7DAR1LtDncEa647ZxgmkoVV",
+ "block_number": 462325,
+ "consensus_hash": "1288cef43f52bf97e2f458a4afe40b61",
+ "first_registered": 462359,
+ "importer": null,
+ "importer_address": null,
+ "keep_data": true,
+ "last_renewed": 462359,
+ "name": "fpenrose.id",
+ "name_hash128": "7af28a9834934a0af81a19ee14a45f8e",
+ "namespace_block_number": 373601,
+ "namespace_id": "id",
+ "op": ">>",
+ "op_fee": 25000,
+ "opcode": "NAME_TRANSFER",
+ "preorder_block_number": 462325,
+ "preorder_hash": "59c25d7cddf433b5122cabcbf2ebcc1bc1519e4d",
+ "revoked": false,
+ "sender": "76a9148e002a93b9b1936b5d320967194eaff3deaa979088ac",
+ "sender_pubkey": null,
+ "txid": "6461bb4bbf517e9c80ffcac4c349836972656572e113aba736b356119655064e",
+ "value_hash": "ac73155702ca7aea1161d0f0c7877ac81d48d8fc",
+ "vtxindex": 637
+ },
+ {
+ "address": "1Q44Md5KFr6gxQ6TdUSFaCRm3MaUyXMF6t",
+ "block_number": 462316,
+ "consensus_hash": "1288cef43f52bf97e2f458a4afe40b61",
+ "first_registered": 462353,
+ "importer": null,
+ "importer_address": null,
+ "keep_data": true,
+ "last_renewed": 462353,
+ "name": "rahulpradhan.id",
+ "name_hash128": "c55ff9e14c72b2950b14ff10067d7e27",
+ "namespace_block_number": 373601,
+ "namespace_id": "id",
+ "op": ">>",
+ "op_fee": 25000,
+ "opcode": "NAME_TRANSFER",
+ "preorder_block_number": 462316,
+ "preorder_hash": "fcb3389ca4d2ab8003ce8b6b3baa0a5ae1600cce",
+ "revoked": false,
+ "sender": "76a914fcdef125f40f984fafad4b58e30e3b1761a953f388ac",
+ "sender_pubkey": null,
+ "txid": "be58e02642c457fec2835a354fbc2de45e8c838aa5b7fd18ed831f67d08269e6",
+ "value_hash": "e213e58ca1446875b79d866720130cc90cbca681",
+ "vtxindex": 638
+ },
+ {
+ "address": "1D8pL725X9HWvoTVgzqDNbTPayHGG7tkY6",
+ "block_number": 462345,
+ "consensus_hash": "919df884f14f34fd15a791af2fddb569",
+ "first_registered": 462380,
+ "importer": null,
+ "importer_address": null,
+ "keep_data": true,
+ "last_renewed": 462380,
+ "name": "sajithskurup.id",
+ "name_hash128": "3fda1c60620c42e1ede385bb246bd5f0",
+ "namespace_block_number": 373601,
+ "namespace_id": "id",
+ "op": ">>",
+ "op_fee": 25000,
+ "opcode": "NAME_TRANSFER",
+ "preorder_block_number": 462345,
+ "preorder_hash": "540daefe1f3b520253f7ab954dbc8bf131471133",
+ "revoked": false,
+ "sender": "76a914851bee0185dd799755234fb20710a26ec40354d288ac",
+ "sender_pubkey": null,
+ "txid": "e7d35196ca3eec697274d848136f5267b1c935055a917020f93e8ecaf821ba99",
+ "value_hash": "92534954e934019718478bb52150765dfad79171",
+ "vtxindex": 644
+ },
+ {
+ "address": "1EbjXtYv9QCVBp8iWiDH6xQ1B74oFW696X",
+ "block_number": 462345,
+ "consensus_hash": "e0c31e03125f2feefd4090e5c635ee45",
+ "first_registered": 462380,
+ "importer": null,
+ "importer_address": null,
+ "keep_data": true,
+ "last_renewed": 462380,
+ "name": "hubject.id",
+ "name_hash128": "03e8bf92dd3cbde65cac012350efb79d",
+ "namespace_block_number": 373601,
+ "namespace_id": "id",
+ "op": ">>",
+ "op_fee": 25000,
+ "opcode": "NAME_TRANSFER",
+ "preorder_block_number": 462345,
+ "preorder_hash": "ded4d097614cf5321388bbe56b24d3d592b2ef76",
+ "revoked": false,
+ "sender": "76a914952b4844005dd98a1f7fc99813db2a649109b45988ac",
+ "sender_pubkey": null,
+ "txid": "7b7a2a2963f7454b93003031cfce64ac609f902b4c2cababfbbfad2c01bbeb9b",
+ "value_hash": "be968a1f17ac828179e5b2fbc70d238056af7482",
+ "vtxindex": 645
+ },
+ {
+ "address": "14YsDo5qgAP7kmnq33tw9JdHVBywpg9pge",
+ "block_number": 462326,
+ "consensus_hash": "e0c31e03125f2feefd4090e5c635ee45",
+ "first_registered": 462354,
+ "importer": null,
+ "importer_address": null,
+ "keep_data": true,
+ "last_renewed": 462354,
+ "name": "ramimassoud.id",
+ "name_hash128": "61a48b6f8aeb027883ecd1f8d808c8ac",
+ "namespace_block_number": 373601,
+ "namespace_id": "id",
+ "op": ">>",
+ "op_fee": 25000,
+ "opcode": "NAME_TRANSFER",
+ "preorder_block_number": 462326,
+ "preorder_hash": "23aa275e42d7d6d7e538584a799252939687c457",
+ "revoked": false,
+ "sender": "76a91426ef31b7aac60eff23cbbab51d453b84700e330388ac",
+ "sender_pubkey": null,
+ "txid": "85babcf66caf41cb7beb2e637cbed4e728ab8030337fb5df8461d0e14dd2be75",
+ "value_hash": "e27c9c3dcce8a8445d84fb8b4d81fbd30fac9749",
+ "vtxindex": 646
+ },
+ {
+ "address": "1H934mT7AVVZmHwjddUZ9EiostLwm655oF",
+ "block_number": 462345,
+ "consensus_hash": "919df884f14f34fd15a791af2fddb569",
+ "first_registered": 462391,
+ "importer": null,
+ "importer_address": null,
+ "keep_data": true,
+ "last_renewed": 462391,
+ "name": "was2bme.id",
+ "name_hash128": "f2b5688682fd47b8f3fbf709bb35ef33",
+ "namespace_block_number": 373601,
+ "namespace_id": "id",
+ "op": ">>",
+ "op_fee": 6250,
+ "opcode": "NAME_TRANSFER",
+ "preorder_block_number": 462345,
+ "preorder_hash": "3dfdcee2b0e64697c4bb0b0dd791518bcb078dc7",
+ "revoked": false,
+ "sender": "76a914b107105f8ae57e7bb5bad58caba666faa679c70f88ac",
+ "sender_pubkey": null,
+ "txid": "16171e4e20778354a94c5353b0c6ed0b29a3e73c1b59b9bfbcbe6d26c570fd0c",
+ "value_hash": "ac73155702ca7aea1161d0f0c7877ac81d48d8fc",
+ "vtxindex": 649
+ },
+ {
+ "address": "1B4zxvVMPm1PBGarc8PrYQjQY2ezwniyG6",
+ "block_number": 462345,
+ "consensus_hash": "e0c31e03125f2feefd4090e5c635ee45",
+ "first_registered": 462391,
+ "importer": null,
+ "importer_address": null,
+ "keep_data": true,
+ "last_renewed": 462391,
+ "name": "tadas_serbenta.id",
+ "name_hash128": "6d800932daf830925ab47dee5ceb8661",
+ "namespace_block_number": 373601,
+ "namespace_id": "id",
+ "op": ">>",
+ "op_fee": 6250,
+ "opcode": "NAME_TRANSFER",
+ "preorder_block_number": 462345,
+ "preorder_hash": "07a85eac4dbf20000a66a14a4a89a01134b70fab",
+ "revoked": false,
+ "sender": "76a9146e72e44bbe4c1706ea5830096a4bb4449dcc948f88ac",
+ "sender_pubkey": null,
+ "txid": "e3f0b019550417a7acfe27addfbd34ec7ec5fc1dd9616ed8c6bc86a0ad148290",
+ "value_hash": "fbac107ba5d9bbfc30ecdeae3e10ca3db72b3431",
+ "vtxindex": 855
+ },
+ {
+ "address": "16BF35VputeLEmbsk7gDnUcwKXcjwPDUvf",
+ "block_number": 462345,
+ "consensus_hash": "919df884f14f34fd15a791af2fddb569",
+ "first_registered": 462359,
+ "importer": null,
+ "importer_address": null,
+ "keep_data": true,
+ "last_renewed": 462359,
+ "name": "alexucf.id",
+ "name_hash128": "d9bc88b0fdc536e7ac5467609faed518",
+ "namespace_block_number": 373601,
+ "namespace_id": "id",
+ "op": ">>",
+ "op_fee": 25000,
+ "opcode": "NAME_TRANSFER",
+ "preorder_block_number": 462345,
+ "preorder_hash": "30f841114af6ada90ba720d563672113c4f74439",
+ "revoked": false,
+ "sender": "76a91438c8814ae2a9035e85bbf2b7976919c2e3387ac588ac",
+ "sender_pubkey": null,
+ "txid": "f8e9eebd48b9182b82b22e5ce10f805d3db38786bb2aaf56f9badf83aa3cc0ee",
+ "value_hash": "8ae0f51263f540be175230d6b46f5d9609de799d",
+ "vtxindex": 856
+ },
+ {
+ "address": "1EmXTRHC6f9bnLJkVZRavv7HLG1owLgNir",
+ "block_number": 462326,
+ "consensus_hash": "31a304b682e3291811441a12f19d14e5",
+ "first_registered": 462391,
+ "importer": null,
+ "importer_address": null,
+ "keep_data": true,
+ "last_renewed": 462391,
+ "name": "seamur.id",
+ "name_hash128": "09f3b9d2da3d0aa1999824f7884f0d18",
+ "namespace_block_number": 373601,
+ "namespace_id": "id",
+ "op": ">>",
+ "op_fee": 100000,
+ "opcode": "NAME_TRANSFER",
+ "preorder_block_number": 462326,
+ "preorder_hash": "678991fd4d3833babe27f732206a40d1f15dd3ca",
+ "revoked": false,
+ "sender": "76a91497055c47fa0ab396fb321e9d37f6bce1796e3d5688ac",
+ "sender_pubkey": null,
+ "txid": "e32124770c359eaf57709e5a666894f2954aa687820c41c6911f214e9006b58e",
+ "value_hash": "4bcdd931185537902ef1af9975198c6404d4c73e",
+ "vtxindex": 857
+ },
+ {
+ "address": "13pGtMcHsNdq3EeLMa1yVVKppP1WjSKgFG",
+ "block_number": 462345,
+ "consensus_hash": "e0c31e03125f2feefd4090e5c635ee45",
+ "first_registered": 462354,
+ "importer": null,
+ "importer_address": null,
+ "keep_data": true,
+ "last_renewed": 462354,
+ "name": "innergame.id",
+ "name_hash128": "a3e4e010d82369ee19b64fccc2b97f69",
+ "namespace_block_number": 373601,
+ "namespace_id": "id",
+ "op": ">>",
+ "op_fee": 25000,
+ "opcode": "NAME_TRANSFER",
+ "preorder_block_number": 462345,
+ "preorder_hash": "f54850caf10c3041cb2a4d9186bbb234dd7d9f85",
+ "revoked": false,
+ "sender": "76a9141ee10ff0ae9969e2dc39d94a959e3160b26b6adf88ac",
+ "sender_pubkey": null,
+ "txid": "28de7193e28e1b0c950a32af393284578669c15dc98bad68f382f8b920d94509",
+ "value_hash": "bab40c2b10f676288edea119edade67ff5e853ba",
+ "vtxindex": 869
+ }
+ ]
+
+ + Schema
+
+ {
+ 'type': 'array',
+ 'items': {
+ 'type': 'object',
+ 'properties': {
+ 'address': {
+ 'type': 'string',
+ 'pattern': "^([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]+)$",
+ },
+ 'base': {
+ 'type': 'integer',
+ 'minimum': 0,
+ 'maximum': 255,
+ },
+ 'buckets': {
+ 'anyOf': [
+ {
+ 'type': 'array',
+ 'items': {
+ 'type': 'integer',
+ 'minItems': 16,
+ 'maxItems': 16,
+ },
+ },
+ {
+ 'type': 'null',
+ },
+ ],
+ },
+ 'block_number': {
+ 'type': 'integer',
+ 'minimum': 0,
+ },
+ 'coeff': {
+ 'anyOf': [
+ {
+ 'type': 'integer',
+ 'minimum': 0,
+ 'maximum': 255,
+ },
+ {
+ 'type': 'null'
+ },
+ ],
+ },
+ 'consensus_hash': {
+ 'anyOf': [
+ {
+ 'type': 'string',
+ 'pattern': '^[0-9a-fA-F]{32}',
+ },
+ {
+ 'type': 'null'
+ },
+ ],
+ },
+ 'domain': {
+ 'type': 'string',
+ 'pattern': '^([a-z0-9\-_.+]{3,37})$',
+ },
+ 'fee': {
+ 'type': 'integer',
+ 'minimum': 0,
+ },
+ 'first_registered': {
+ 'type': 'integer',
+ 'minimum': 0,
+ },
+ 'history_snapshot': {
+ 'type': 'boolean',
+ },
+ 'importer': {
+ 'anyOf': [
+ {
+ 'type': 'string',
+ 'pattern': '^76[aA]914[0-9a-fA-F]{40}88[aA][cC]$',
+ },
+ {
+ 'type': 'null',
+ },
+ ],
+ },
+ 'importer_address': {
+ 'anyOf': [
+ {
+ 'type': 'string',
+ 'pattern': "^([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]+)$",
+ },
+ {
+ 'type': 'null',
+ },
+ ],
+ },
+ 'last_renewed': {
+ 'type': 'integer',
+ 'minimum': 0,
+ },
+ 'name': {
+ 'type': 'string',
+ 'pattern': '^([a-z0-9\\-_.+]{3,37})\.([a-z0-9\\-_.+]{3,37})$',
+ },
+ 'op': {
+ 'type': 'string',
+ 'pattern': '^([>?+~:!&*:;#]{1}|>>|>~|::)$',
+ },
+ 'op_fee': {
+ 'type': 'number',
+ },
+ 'opcode': {
+ 'type': 'string',
+ 'pattern': '^NAME_TRANSFER|NAME_PREORDER|NAME_UPDATE|NAME_REVOKE|NAME_REGISTRATION|NAMESPACE_READY|NAMESPACE_REVEAL|NAMESPACE_PREORDER|NAME_RENEWAL|NAME_IMPORT|ANNOUNCE$'
+ },
+ 'revoked': {
+ 'type': 'boolean',
+ },
+ 'sender': {
+ 'type': 'string',
+ 'pattern': '^([0-9a-fA-F]+)$',
+ },
+ 'sender_pubkey': {
+ 'anyOf': [
+ {
+ 'type': 'string',
+ 'pattern': '^([0-9a-fA-F]+)$',
+ },
+ {
+ 'type': 'null'
+ },
+ ],
+ },
+ 'sequence': {
+ 'type': 'integer',
+ 'minimum': 0
+ }
+ 'recipient': {
+ 'anyOf': [
+ {
+ 'type': 'string',
+ 'pattern': '^([0-9a-fA-F]+)$',
+ },
+ {
+ 'type': 'null'
+ },
+ ],
+ },
+ 'recipient_address': {
+ 'anyOf': [
+ {
+ 'type': 'string',
+ 'pattern': '^([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]+)$',
+ },
+ {
+ 'type': 'null'
+ },
+ ],
+ },
+ 'recipient_pubkey': {
+ 'anyOf': [
+ {
+ 'type': 'string',
+ 'pattern': '^([0-9a-fA-F]+)$',
+ },
+ {
+ 'type': 'null'
+ },
+ ],
+ },
+ 'txid': {
+ 'type': 'string',
+ 'pattern': '^([0-9a-fA-F]+)$',
+ },
+ 'value_hash': {
+ 'anyOf': [
+ {
+ 'type': 'string',
+ 'pattern': '^([0-9a-fA-F]{40})$',
+ },
+ {
+ 'type': 'null',
+ },
+ ],
+ },
+ 'vtxindex': {
+ 'type': 'integer',
+ 'minimum': 0,
+ },
+ },
+ 'required': [
+ 'txid',
+ 'vtxindex'
+ ],
+ }
+ }
+ }
+
++ Response 400 (application/json)
+ + Body
+
+ { "error": "Invalid name or subdomain" }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'error': { 'type': 'string' },
+ },
+ }
+
++ Response 404 (application/json)
+ + Body
+
+ { "error": "No such name" }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'error': { 'type': 'string' },
+ },
+ }
+
+# Group Namespace Operations
+
+## Get all namespaces [GET /v1/namespaces]
++ Public Endpoint
++ Response 200 (application/json)
+ + Body
+
+ {
+ "namespaces": [
+ "id"
+ ]
+ }
+
+ + Schema
+ {
+ 'type': 'object',
+ 'properties': {
+ 'namespaces': {
+ 'type': 'array',
+ 'items': { 'type': 'string' }
+ }
+ },
+ 'required': [ 'namespaces' ]
+ }
+
+## Get namespace names [GET /v1/namespaces/{tld}/names?page={page}]
+
+Fetch a list of names from the namespace.
++ Public Endpoint
++ Parameters
+ + tld: id (string) - the namespace to fetch names from
+ + page: 23 (number) - names are returned in pages of size 100,
+ so specify the page number.
++ Response 200 (application/json)
+ + Body
+
+ [ "aldenquimby.id", "aldeoryn.id",
+ "alderete.id", "aldert.id",
+ "aldi.id", "aldighieri.id", ... ]
+
+ + Schema
+
+ {
+ 'type': 'array',
+ 'items': {
+ 'type': 'string',
+ 'pattern': '^([a-z0-9\-_.+]{3,37})$'
+ }
+ }
+
++ Response 400 (application/json)
+ + Body
+
+ { "error": "Invalid page" }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'error': { 'type': 'string' },
+ },
+ }
+
++ Response 404 (application/json)
+ + Body
+
+ { "error": "No such namespace" }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'properties': {
+ 'error': { 'type': 'string' },
+ },
+ }
+
+# Group Resolver Endpoints
+
+## Lookup User [GET /v1/users/{username}]
+Lookup and resolver a user's profile. Defaults to the `id` namespace.
+Note that [blockstack.js](https://github.com/blockstack/blockstack.js) does
+*not* rely on this endpoint.
+
++ Public Endpoint
++ Subdomain Aware
++ Legacy Endpoint
++ Parameters
+ + username: fred (string) - username to lookup
++ Response 200 (application/json)
+
+ {
+ "fred.id": {
+ "owner_address": "1CER5u4QXuqffHjHKrU76iMCsqtJLM5VHu",
+ "profile": {
+ "@context": "http://schema.org",
+ "@type": "Person",
+ "account": [
+ {
+ "@type": "Account",
+ "identifier": "fredwilson",
+ "placeholder": false,
+ "proofType": "http",
+ "proofUrl": "https://twitter.com/fredwilson/status/943066895422455809",
+ "service": "twitter"
+ }
+ ],
+ "description": "I am a VC",
+ "image": [
+ {
+ "@type": "ImageObject",
+ "contentUrl": "https://gaia.blockstack.org/hub/1CER5u4QXuqffHjHKrU76iMCsqtJLM5VHu/0/avatar-0",
+ "name": "avatar"
+ }
+ ],
+ "name": "Fred Wilson"
+ },
+ "public_key": "026c94d1897fa148fa6401247a339b55abd869a3d562fdae8a7fcb9a11f1f846f3",
+ "verifications": [
+ {
+ "identifier": "fredwilson",
+ "proof_url": "https://twitter.com/fredwilson/status/943066895422455809",
+ "service": "twitter",
+ "valid": true
+ }
+ ],
+ "zone_file": {
+ "$origin": "fred.id",
+ "$ttl": 3600,
+ "uri": [
+ {
+ "name": "_http._tcp",
+ "priority": 10,
+ "target": "https://gaia.blockstack.org/hub/1CER5u4QXuqffHjHKrU76iMCsqtJLM5VHu/0/profile.json",
+ "weight": 1
+ }
+ ]
+ }
+ }
+ }
+
+ + Schema
+ {
+ 'type': 'object',
+ 'patternProperties': {
+ '^([a-z0-9\\-_.+]{3,37})\.([a-z0-9\\-_.+]{3,37})$|^([a-z0-9\\-_.+]){3,37}$': {
+ 'type': 'object',
+ 'properties': {
+ 'owner_address': { 'type': 'string', 'pattern': "^([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]+)$" },
+ 'profile' : { 'type': 'object' },
+ 'public_key': { 'type': 'string', 'pattern': "^([0-9a-fA-F]$" },
+ 'verifications: {
+ 'type': 'array',
+ 'items': {
+ 'type': 'object',
+ 'properties': {
+ 'identifier': { 'type': 'string' },
+ 'proof_url': { 'type': 'string' },
+ 'service': { 'type': 'string' },
+ 'valid': { 'type': 'boolean' }
+ },
+ }
+ },
+ 'zone-file': { 'type': 'object' }
+ }
+ }
+ }
+ }
+
++ Response 404 (application/json)
+ + Body
+
+ {
+ "nope.none": {
+ "error": "Name has no user record hash defined"
+ }
+ }
+
+ + Schema
+
+ {
+ 'type': 'object',
+ 'patternProperties': {
+ '^([a-z0-9\\-_.+]{3,37})\.([a-z0-9\\-_.+]{3,37})$|^([a-z0-9\\-_.+]){3,37}$': {
+ 'type': 'object',
+ 'properties': {
+ 'error': { 'type': 'string' }
+ },
+ 'required': [ 'error' ]
+ }
+ }
+ }
+
+## Profile Search [GET /v1/search?query={query}]
+Searches for a profile using a search string.
++ Public Only Endpoint
++ Parameters
+ + query: wenger (string) - the search query
++ Response 200 (application/json)
+ + Body
+
+ {
+ "results": [
+ {
+ "fullyQualifiedName": "albertwenger.id",
+ "username": "albertwenger",
+ "profile": {
+ "@type": "Person",
+ "account": [
+ {
+ "@type": "Account",
+ "identifier": "albertwenger",
+ "proofType": "http",
+ "service": "twitter"
+ },
+ {
+ "@type": "Account",
+ "identifier": "albertwenger",
+ "proofType": "http",
+ "service": "facebook"
+ },
+ {
+ "@type": "Account",
+ "identifier": "albertwenger",
+ "proofType": "http",
+ "service": "github"
+ },
+ {
+ "@type": "Account",
+ "identifier": "1QHDGGLEKK7FZWsBEL78acV9edGCTarqXt",
+ "role": "payment",
+ "service": "bitcoin"
+ }
+ ],
+ "address": {
+ "@type": "PostalAddress",
+ "addressLocality": "New York"
+ },
+ "description": "VC at USV.com",
+ ...
+ }
+
+ + Schema
+ {
+ 'type': 'object',
+ 'properties': {
+ 'results': {
+ 'type': 'array',
+ 'items': {
+ 'fullyQualifiedName': { 'type': 'string', 'pattern': '^([a-z0-9\\-_.+]{3,37})\.([a-z0-9\\-_.+]{3,37})$|^([a-z0-9\\-_.+]){3,37}$' },
+ 'username': { 'type': 'string' },
+ 'profile' : { 'type': 'object' },
+ }
+ }
+ }
+ }
+
diff --git a/_core/atlas/howitworks.md b/_core/atlas/howitworks.md
new file mode 100644
index 00000000..3e9df493
--- /dev/null
+++ b/_core/atlas/howitworks.md
@@ -0,0 +1,184 @@
+---
+layout: core
+permalink: /:collection/:path.html
+---
+# How Atlas Works
+{:.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.
+
+This section contains the following sections:
+
+* TOC
+{:toc}
+
+## Peer Selection
+
+Atlas peers self-organize into an unstructured peer-to-peer network.
+The Atlas peer network is a [random K-regular
+graph](https://en.wikipedia.org/wiki/Random_regular_graph). Each node maintains
+*K* neighbors chosen at random from the set of Atlas peers.
+
+Atlas nodes select peers by carrying out an unbiased random walk of the peer
+graph. When "visiting" a node *N*, it will ask for *N*'s neighbors and then
+"step" to one of them with a probability dependent on *N*'s out-degree and the
+neighbor's in-degree.
+
+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:
+
+* If the neighbors of the visited node *N* 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.
+
+* The transition probability from *N* to a live neighbor is *NOT* `min(1,
+degree(neighbor)/degree(N))` like it is in the vanilla MH algorithm. Instead,
+the transition probability discourages backtracking to the previous neighbor *N_prev*,
+but in a way that still guarantees that the sampling will remain unbiased.
+
+* 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.
+
+* A new neighbor is only selected if it belongs to the same [BNS
+ fork-set]({{site.baseurl}}/core/naming/introduction.html#bns-forks) (i.e. it reports
+as having a recent valid consensus hash).
+
+The algorithm was adapted from the work from [Lee, Xu, and
+Eun](https://arxiv.org/pdf/1204.4140.pdf) in the proceedings of
+ACM SIGMETRICS 2012.
+
+## Comparison to DHTs
+
+The reason Atlas uses an unstructured random peer network
+instead of a [distributed hash table](https://en.wikipedia.org/wiki/Distributed_hash_table)
+(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.
+
+### Chunk Censorship
+
+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 *fundamental* 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.
+
+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 *independent* of the content and *randomized* 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).
+
+### Neighbor Censorship
+
+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).
+
+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.
+
+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.
+
+## Chunk Propagation
+
+Atlas nodes maintain an *inventory* 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.
+
+Atlas peers keep track of which chunks are present and which are absent. They
+each construct an *inventory vector* of chunks *V* such that *V[i]* is set to 1
+if the node has the chunk whose hash is in the *i*th position in the chunk
+sequence (and set to 0 if it is absent).
+
+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.
+
+```
+ 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.
+```
+
+## Querying Chunk Inventories
+
+Developers can query a node's inventory vector as follows:
+
+```python
+>>> import blockstack
+>>> result = blockstack.lib.client.get_zonefile_inventory("https://node.blockstack.org:6263", 0, 524288)
+>>> print len(result['inv'])
+11278
+>>>
+```
+
+The variable `result['inv']` here is a big-endian bit vector, where the *i*th
+bit is set to 1 if the *i*th chunk in the chunk sequence is present. The bit at
+`i=0` (the earliest chunk) refers to the leftmost bit.
+
+A sample program that inspects a set of Atlas nodes' inventory vectors and determines
+which ones are missing which chunks can be found
+[here](https://github.com/blockstack/atlas/blob/master/atlas/atlas-test).
diff --git a/_core/atlas/howtouse.md b/_core/atlas/howtouse.md
new file mode 100644
index 00000000..b80a7dbe
--- /dev/null
+++ b/_core/atlas/howtouse.md
@@ -0,0 +1,127 @@
+---
+layout: core
+permalink: /:collection/:path.html
+---
+# How to Use the Atlas Network
+{:.no_toc}
+
+This section teaches you how to use the Atlas network, it contains the
+following sections:
+
+* TOC
+{:toc}
+
+## The API
+
+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.
+
+The [public BNS API endpoint](https://core.blockstack.org) 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
+[Blockstack Core](https://github.com/blockstack/blockstack-core) and use its
+Python client libraries for these examples.
+
+## Looking up Chunks
+
+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.
+
+A client can look up a chunk with the `get_zonefiles()` method. If successful,
+the returned payload will be a `dict` with a `zonefiles` key that maps the chunk
+hashes to their respective data.
+
+```python
+>>> import blockstack
+>>> data = blockstack.lib.client.get_zonefiles('https://node.blockstack.org:6263', ['1b89a685f4c4ea245ce9433d0b29166c22175ab4'])
+>>> print data['zonefiles']['1b89a685f4c4ea245ce9433d0b29166c22175ab4']
+$ORIGIN duckduckgo_tor.id
+$TTL 3600
+tor TXT "3g2upl4pq6kufc4m.onion"
+
+>>>
+```
+
+(This particular chunk happens to be associated with the BNS name
+`duckduckgo_tor.id`).
+
+## Adding a New Chunk
+
+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:
+
+* The name owner announces the chunk hash as a name's state
+via a `NAME_REGISTRATION`, `NAME_UPDATE`, `NAME_RENEWAL`, or `NAME_IMPORT` transaction.
+* Once the transaction is confirmed and processed by BNS, the name owner
+ broadcasts the matching zone file.
+
+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
+[blockstack.js](https://github.com/blockstack/blockstack.js) and the [Blockstack
+Browser](https://github.com/blockstack/blockstack-browser) for doing this.
+
+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:
+
+```python
+>>> import blockstack
+>>> import base64
+>>> data = "..." # this is the chunk data you will announce
+>>> data_b64 = base64.b64encode(data)
+>>> result = blockstack.lib.client.put_zonefiles('https://node.blockstack.org:6263', [data_b64])
+>>> assert result['saved'][0] == 1
+>>>
+```
+
+At most five chunks can be announced in one RPC call.
+Note that the data must be base64-encoded before it can be announced.
+
+When the `put_zonefiles()` method succeeds, it returns a `dict` with a list
+under the `saved` key. Here, `result['saved'][i]` will be 1 if the `i`th
+chunk given to `put_zonefiles()` 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.
+
+The `put_zonefiles()` method is idempotent.
+
+## Propagating Chunks
+
+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.
+
+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.
+
+For example, this code will replicate the chunk to not only
+`https://node.blockstack.org:6263`, but also to its immediate neighbors.
+
+```python
+>>> import blockstack
+>>> import base64
+>>> data = "..." # this is the chunk you will replicate widely
+>>> data_b64 = base64.b64encode(data)
+>>>
+>>> result = blockstack.lib.client.get_atlas_peers('https://node.blockstack.org:6263')
+>>> neighbors = result['peers']
+>>> print ", ".join(neighbors)
+13.65.207.163:6264, 52.225.128.191:6264, node.blockstack.org:6264, 23.102.162.7:6264, 52.167.230.235:6264, 23.102.162.124:6264, 52.151.59.26:6264, 13.92.134.106:6264
+>>>
+>>> for neighbor in neighbors:
+... result = blockstack.lib.client.put_zonefiles(neighbor, [data_b64])
+... assert result['saved'][0] == 1
+...
+>>>
+```
+
+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.
diff --git a/_core/atlas/overview.md b/_core/atlas/overview.md
new file mode 100644
index 00000000..4f097de3
--- /dev/null
+++ b/_core/atlas/overview.md
@@ -0,0 +1,126 @@
+---
+layout: core
+permalink: /:collection/:path.html
+---
+# Overview of the Atlas network
+{:.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 **permanently store** chunks of data that are
+**replicated across every peer.** As long as at least one Atlas peer is online,
+all chunks are available to clients.
+
+This document is aimed at developers and technical users. The following
+concepts are discussed:
+
+* TOC
+{:toc}
+
+The reader of this document is expected to be familiar with the [Blockstack Naming Service]({{site.baseurl}}/core/naming/introduction.html)(BNS), as well as Blockstack's
+storage system [Gaia](https://github.com/blockstack/gaia). We advise the reader
+to familiarize themselves with both systems before approaching this document.
+
+## Architecture
+
+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:
+
+* Storing a name's routing information for its owners' [Gaia](https://github.com/blockstack/gaia)
+datastores.
+* Storing BNS subdomain transactions and associated state.
+
+Atlas is a middleware system in Blockstack. Most developers do not
+interact with it directly. BNS clients like the
+[Blockstack Browser](https://github.com/blockstack/blockstack-browser)
+automatically generate zone files for the names they register, and automatically
+propagate them to the Atlas network. BNS API endpoints, including our
+[public endpoint](https://core.blockstack.org) and the
+[blockstack.js](https://github.com/blockstack/blockstack.js) library,
+will automatically fetch zone files from Atlas when they need to look
+up data in Gaia (such as profiles and app data).
+
+```
+ +--------------+ +---------------+ +----------------+
+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.
+```
+
+Nevertheless, Atlas is a general-purpose content-addressed storage
+system that advanced developers can use to **host data in an immutable
+and durable manner.** Beyond its default use-case in Blockstack,
+Atlas is ideal for tasks like:
+
+* Announcing PGP public keys under a human-readable name
+* Storing package hashes for a software release
+* Securely deploying shell scripts to remote VMs
+* Binding human-readable names to Tor .onion addresses
+ ([example](https://github.com/blockstack-packages/blockstack-tor))
+
+## Motivation
+
+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.
+
+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
+*preserves the security properties of having written that state to the
+blockchain*. Instead of storing 20 bytes of data on the blockchain, a BNS name
+owner would store the *cryptograhpic hash* of its state, and then store the actual state
+Atlas. This decouples the name's state size from the blockchain.
+
+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.
+
+## Feature Comparison
+
+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.
+
+| **Features** | Atlas | BitTorrent | [DAT](https://datproject.org/) | [IPFS](https://ipfs.io) | [Swarm](https://github.com/ethersphere/swarm) |
+|-----------------------------|-------|------------|--------------------------------|-------------------------|-----------------------------------------------|
+| Each peer stores all chunks | X | X | | | |
+| Replicas are permanent [1] | X | X | X | | |
+| Replicas are free | | X | X | X | |
+| Sybil-resistant chunk discovery | X | X | | | X |
+| Sybil-resistant peer discovery | X | | | | |
+| Fixed chunk size | X | | X | X | X |
+
+[1] Here, "permanent" means that once a peer has data, they will never evict it
+as part of the protocol.
diff --git a/_core/atlas_network.md b/_core/atlas_network.md
new file mode 100644
index 00000000..ecdb12ac
--- /dev/null
+++ b/_core/atlas_network.md
@@ -0,0 +1 @@
+The documentation has been moved to [docs.blockstack.org](https://docs.blockstack.org/), please update your bookmarks.
diff --git a/_core/attic/README.md b/_core/attic/README.md
new file mode 100644
index 00000000..9871c12c
--- /dev/null
+++ b/_core/attic/README.md
@@ -0,0 +1,4 @@
+# Legacy, Deprecated, or No longer Useful Documentation
+
+Documents here are out-of-date but preserved for posterity. Do not rely on
+them.
diff --git a/_core/attic/advanced_usage.md b/_core/attic/advanced_usage.md
new file mode 100644
index 00000000..5d75b35e
--- /dev/null
+++ b/_core/attic/advanced_usage.md
@@ -0,0 +1,124 @@
+# Advanced Usage
+
+This section details some of the advanced features in the CLI.
+
+## A Word of Warning
+
+Advanced features are meant to be used by experienced Blockstack users and developers, They receive less UI/UX testing than basic features, and their interfaces are expected to change to accomodate bugfixes and security fixes. Moreover, improper use of some advanced methods can cost you money, corrupt your profile, or compromise your wallet. Once they receive sufficient testing, an advanced feature may become a basic-mode feature in a subsequent release.
+
+**Do not use advanced mode unless you know what you are doing!**
+
+## Activating Advanced Mode
+
+To activate advanced mode, use the command `blockstack set_advanced_mode on`.
+
+To deactivate it later (recommended), use the command `blockstack set_advanced_mode off`.
+
+## Changing or Using Exiting Keys
+
+If you already have a payment key you want to use, or an owner key you want to migrate over, you can generate a wallet directly with `import_wallet`. We recommend using this command interactively, so you know which keys correspond to which usages.
+
+## Accounts
+
+With the accounts methods, you can directly manage your social proofs, link existing services to your profile, and store small bits of information.
+
+The account management methods are:
+* `get_account`: Look up an account in a name's profile. There can be more than one match.
+* `list_accounts`: List all accounts in a name's profile.
+* `put_account`: Add or update an account in a name's profile.
+* `delete_account`: Remove an account from a name's profile. This may need to be done more than once, if there are duplicates of the account.
+
+## Advanced Blockstack ID Queries
+
+Beyond `lookup` and `whois`, there are a few other more advanced queries you can run on Blockstack IDs. These include:
+
+### Listing Blockstack IDs
+* `get_all_names`: Get the list of every single Blockstack ID in existance.
+* `get_names_owned_by_address`: Get the list of names owned by a particular ownership address.
+
+### Querying the Blockchain
+* `get_name_blockchain_record`: Get the raw database record for a Blockstack ID. It will contain a *compressed* history of all name operations that have affected it. This is meant primarily for debugging purposes; to get an easier-to-parse listing of the information this command returns, use `get_name_blockchain_history`.
+* `get_name_blockchain_history`: Get the set of all prior states a Blockstack ID has been in, keyed by the block heights at which the state-change was processed.
+* `get_records_at`: Get the list of name operation records processed at a particular block height.
+* `list_update_history`: Get the list of all zonefile hashes that a Blockstack ID has ever had.
+
+### Zonefiles
+* `get_name_zonefile`: Get only a Blockstack ID's zonefile.
+* `list_zonefile_history`: Get the list of all zonefiles a Blockstack ID has ever had. **NOTE:** There is no guarantee that the server will hold copies of old zonefiles. This command is meant mainly for determining which historic zonefiles a server has processed.
+* `set_zonefile_hash`: This is the counterpart to `update`, but instead of setting the zonefile directly and uploading it to storage, you can use this command to directly set the data hash for a Blockstack ID. **NOTE:** You should ensure that the associated zonefile data has been replicated off-chain to a place where other users can get at it.
+
+### Lightweight Queries
+
+The lightweight lookup protocol for Blockstack is called *Simplified Name Verification* (SNV). This command returns a prior blockchain-level record given a more recent known-good consensus hash, serial number, or transaction ID of a transaction that contains a consensus hash. The CLI does not need to trust the Blockstack server to use these commands.
+
+* `lookup_snv`: Use the Merkle skip-list in the name database to look up a historic name operation on a Blockstack ID.
+
+## Consensus Queries
+
+You can query consensus hash information from the server with the following commands:
+
+* `consensus`: Get the consensus hash at a particular block height
+
+## Namespace Queries
+
+In addition to querying Blockstack IDs, the CLI has advanced commands for querying namespaces. These include:
+
+* `get_namespace_blockchain_record`: Get the raw database record for a Blockstack namespace. It will contain a *compressed* history of all namespace operations that have affected it.
+* `get_names_in_namespace`: Get the list of every Blockstack ID in a particular namespace.
+* `get_namespace_cost`: Get the cost required to preorder a namespace. Does *not* include the cost to reveal and ready it, nor does it include the transaction fees.
+
+## Namespace Creation
+
+**WARNING:** We do not recommend that you try to do this by yourself. Creating a namespace is **EXTREMELY EXPENSIVE**. If you are interested in creating your own namespace, please contact the Blockstack developers on the [Blockstack Slack](http://chat.blockstack.org).
+
+These methods allow you to create a namespace. There are three steps: preordering, revealing, and readying. Preordering a namespace is like preordering a name--you announce the hash of the namespace ID and the address that will control it. Revealing a namespace not only reveals the namespace ID, but also sets the pricing and lifetime rules for names in the namespace. After revealing the namespace, the namespace controller can pre-populate the namespace by importing Blockstack IDs. Once the namespace has been pre-populated, the controller sends a final transaction that readies the namespace for general use.
+
+* `namespace_preorder`: Preorder a namespace.
+* `namespace_reveal`: Reveal a namespace, and set its pricing and lifetime parameters. **NOTE:** This must be done within 144 blocks of sending the namespace preorder transaction.
+* `name_import`: Import a name into a revealed (but not readied) namespace. You can set its owner address and zonefile hash directly.
+* `namespace_ready`: Open a namespace for general registrations.
+
+## Data Storage
+
+Blockstack allows users to store arbitrary data to any set of storage providers for which the CLI has a driver. The data will be signed by the user's data key, so when other users read the data later on, they can verify that it is authentic (i.e. the storage provider is not trusted). Moreover, Blockstack is designed such that users don't have to know or care about which storage providers were used--as far as users can see, storage providers are just shared hard drives.
+
+There are two types of data supported by Blockstack: *mutable* data, and *immutable* data. Mutable data is linked by the profile, and can be written as fast and as frequently as the storage provider allows. Mutable data is addressed by URL.
+
+**WARNING:** While mutable data guarantees end-to-end authenticity, there is a chance that a malicious storage provider can serve new readers stale versions of the data. That is, users who have read the latest data already will not get tricked into reading stale data, but users who have *not yet* read the latest data *can* be tricked (i.e. the CLI keeps a version number for mutable data to do so). This must be taken into account if you intend to use this API.
+
+Immutable data, however, is content-addressed, and its cryptographic hash is stored to the user's zonefile. Writing immutable data will entail updating the zonefile and sending an `update` transaction (handled internally), so it will be slow by comparison. This has the advantage that storage providers cannot perform the aforementioned stale data attack, but has the downside that writes cost money and take a long time to complete.
+
+That said, we recommend using the mutable data API with several different storage providers whenever possible.
+
+### Mutable Data
+
+The following commands affect mutable data:
+
+* `get_mutable`: Use the profile to look up and fetch a piece of mutable data.
+* `put_mutable`: Add a link to mutable data to the profile, and replicate the signed data itself to all storage providers. Other users will need the data's name to read it with `get_mutable`.
+* `delete_mutable`: Remove a link to mutable data from the profile, and ask all storage providers to delete the signed data.
+
+### Immutable Data
+
+The following commnds affect immutable data:
+
+* `get_immutable`: Look up and fetch a piece of immutable data. You can supply either the name of the data, or its hash (both are stored in the zonefile, so there is no gain or loss of security in this choice).
+* `put_immutable`: Replicate a piece of data to all storage providers, add its name and hash to the zonefile, and issue an `update` to upload the new zonefile to Blockstack servers and write the hash to the blockchain.
+* `delete_immutable`: Remove the link to the data from the zonefile, ask all storage providers to delete the data, and issue an `update` to upload the new zonefile to Blockstack servers and write the new hash to the blockchain.
+* `list_immutable_data_history`: Given the name of a piece of immutable data, query the zonefile history to find the historic list of hashes it has had. **NOTE:** Like `list_zonefile_history` above, this only returns data hashes for the data if the Blockstack server has the historic zonefile.
+
+## Fault Recovery
+
+Sometimes, things beyond our control can happen. Transactions can get stuck, storage providers can go offline or corrupt data, and so on. These commands are meant to assist in recovering from these problems:
+
+* `set_profile`: Directly set a Blockstack ID's profile. All previous accounts, data links, etc. must be included in the new profile, since the old profile (if still present) will be overwritten by the one given here.
+* `convert_legacy_profile`: Given a legacy profile taken from a resolver, directly convert it into a new profile. This can be used with `set_profile` to recover from a failed profile migration.
+* `unqueue`: If a transaction gets lost or stuck, you can remove it from the CLI's transaction queue with this command. This will allow you to re-try it.
+* `rpcctl`: This lets you directly start or stop the Blockstack CLI's background daemon, which lets you recover from any crashes it experiences (you can find a trace of its behavior in `~/.blockstack/api_endpoint.log`)
+
+## Programmatic Access
+
+Other programs may want to make RPC calls the Blockstack CLI daemon. They can do so using either the `blockstack_client` Python package, or they can do so via the CLI as follows:
+
+* `rpc`: Issue a JSON RPC call. Takes a raw JSON string that encodes a list of arguments.
+
diff --git a/_core/attic/figures/gaia-authentication.png b/_core/attic/figures/gaia-authentication.png
new file mode 100644
index 00000000..03ca186e
Binary files /dev/null and b/_core/attic/figures/gaia-authentication.png differ
diff --git a/_core/attic/figures/gaia-connect.png b/_core/attic/figures/gaia-connect.png
new file mode 100644
index 00000000..34ab7947
Binary files /dev/null and b/_core/attic/figures/gaia-connect.png differ
diff --git a/_core/attic/figures/gaia-getfile.png b/_core/attic/figures/gaia-getfile.png
new file mode 100644
index 00000000..29d87c72
Binary files /dev/null and b/_core/attic/figures/gaia-getfile.png differ
diff --git a/_core/attic/figures/gaia-listdir.png b/_core/attic/figures/gaia-listdir.png
new file mode 100644
index 00000000..b48072b7
Binary files /dev/null and b/_core/attic/figures/gaia-listdir.png differ
diff --git a/_core/attic/figures/gaia-putfile.png b/_core/attic/figures/gaia-putfile.png
new file mode 100644
index 00000000..6ad02a5b
Binary files /dev/null and b/_core/attic/figures/gaia-putfile.png differ
diff --git a/_core/attic/gaia.md b/_core/attic/gaia.md
new file mode 100644
index 00000000..b63e0536
--- /dev/null
+++ b/_core/attic/gaia.md
@@ -0,0 +1,461 @@
+# LEGACY DOCUMENTATION
+
+Please see the [latest Gaia documentation](https://github.com/blockstack/gaia)
+
+Gaia: The Blockstack Storage System
+====================================
+
+The Blockstack storage system, called "Gaia", is used to host each user's data
+without requiring users to run their own servers.
+
+Gaia works by hosting data in one or more existing storage systems of the user's choice.
+These storage systems include cloud storage systems like Dropbox and Google
+Drive, they include personal servers like an SFTP server or a WebDAV server, and
+they include decentralized storage systems like BitTorrent or IPFS. The point
+is, the user gets to choose where their data lives, and Gaia enables
+applications to access it via a uniform API.
+
+A high-level analogy is to compare Gaia to the VFS and block layer in a UNIX
+operating system kernel, and to compare existing storage systems to block
+devices. Gaia has "drivers" for each storage system that allow it to load,
+store, and delete chunks of data via a uniform interface, and it gives
+applications a familiar API for organizing their data.
+
+Applications interface with Gaia via the [Blockstack Core
+API](https://github.com/blockstack/blockstack-core/tree/master/api). Javascript
+applications connect to Gaia using [Blockstack Portal](https://github.com/blockstack/blockstack-portal),
+which helps them bootstrap a secure connection to Blockstack Core.
+
+# Datastores
+
+Gaia organizes data into datastores. A **datastore** is a filesystem-like
+collection of data that is backed by one or more existing storage systems.
+
+When a user logs into an application, the application will create or connect to
+the datastore that holds the user's data. Once connected, it can proceed to
+interact with its data via POSIX-like functions: `mkdir`, `listdir`, `rmdir`,
+`getFile`, `putFile`, `deleteFile`, and `stat`.
+
+A datastore has exactly one writer: the user that creates it. However, all data
+within a datastore is world-readable by default, so other users can see the
+owner's writes even when the owner is offline. Users manage access controls
+by encrypting files and directories to make them readable to other specific users.
+All data in a datastore is signed by a datastore-specific key on write, in order
+to guarantee that readers only consume authentic data.
+
+The application client handles all of the encryption and signing. The other
+participants---Blockstack Portal, Blockstack Core, and the storage
+systems---only ferry data back and forth between application clients.
+
+## Data Organization
+
+True to its filesystem inspiration, data in a datastore is organized into a
+collection of inodes. Each inode has two parts:
+
+* a **header**, which contains:
+
+ * the inode type (i.e. file or directory)
+
+ * the inode ID (i.e. a UUID4)
+
+ * the hash of the data it stores
+
+ * the size of the data it stores
+
+ * a signature from the user
+
+ * the version number
+
+ * the ID of the device from which it was sent (see Advanced Topics below)
+
+* a **payload**, which contains the raw bytes to be stored.
+
+ * For files, this is just the raw bytes.
+
+ * For directories, this is a serialized data structure that lists the names
+ and inode IDs of its children, as well as a copy of the header.
+
+The header has a fixed length, and is somewhat small--only a few hundred bytes.
+The payload can be arbitrarily large.
+
+## Data Consistency
+
+The reason for organizing data this way is to make cross-storage system reads
+efficient, even when there are stale copies of the data available. In this
+organization, reading an inode's data is a matter of:
+
+1. Fetching all copies of the header
+
+2. Selecting the header with the highest version number
+
+3. Fetching the payload from the storage system that served the latest header.
+
+This way, we can guarantee that:
+
+* The inode payload is fetched *once* in the common case, even if there are multiple stale copies of the inode available.
+
+* All clients observe the *strongest* consistency model offerred by the
+ underlying storage providers.
+
+* All readers observe a *minimum* consistency of monotonically-increasing reads.
+
+* Writers observe sequential consistency.
+
+This allows Gaia to interface with decentralized storage systems that make
+no guarantees regarding data consistency.
+
+*(Aside 1: The Core node keeps track of the highest last-seen inode version number,
+so if all inodes are stale, then no data will be returned).*
+
+*(Aside 2: In step 3, an error path exists whereby all storage systems will be
+queried for the payload if the storage system that served the fresh inode does
+not have a fresh payload).*
+
+# Accessing the Datastore
+
+Blockstack applications get access to the datastore as part of the sign-in
+process. Suppose the user wishes to sign into the application `foo.app`. Then,
+the following protocol is executed:
+
+![Gaia authentication](/docs/figures/gaia-authentication.png)
+
+1. Using `blockstack.js`, the application authenticates to Blockstack Portal via
+`makeAuthRequest()` and `redirectUserToSignIn()`.
+
+2. When Portal receives the request, it contacts the user's Core node to get the
+ list of names owned by the user.
+
+3. Portal redirects the user to a login screen, and presents the user with the
+ list of names to use. The user selects which name to sign in as.
+
+4. Now that Portal knows which name to use, and which application is signing in,
+ it loads the datastore private key and requests a Blockstack Core session
+token. This token will be used by the application to access Gaia.
+
+5. Portal creates an authentication response with `makeAuthResponse()`, which it
+ relays back to the application.
+
+6. The application retrieves the datastore private key and the Core session
+ token from the authentication response object.
+
+
+## Creating a Datastore
+
+Once the application has a Core session token and the datastore private key, it
+can proceed to connect to it, or create it if it doesn't exist. To do so, the
+application calls `datastoreConnectOrCreate()`.
+
+This method contacts the Core node directly. It first requests the public
+datastore record, if it exists. The public datastore record
+contains information like who owns the datastore, when it was created, and which
+drivers should be used to load and store its data.
+
+![Gaia connect](/docs/figures/gaia-connect.png)
+
+Suppose the user signing into `foo.app` does not yet have a datastore, and wants
+to store her data on storage providers `A`, `B`, and `C`. Then, the following
+protocol executes:
+
+1. The `datastoreConnectOrCreate()` method will generate a signed datastore record
+stating that `alice.id`'s public key owns the datastore, and that the drivers
+for `A`, `B`, and `C` should be loaded to access its data.
+
+2. The `datastoreConnectOrCreate()` method will call `mkdir()` to create a
+signed root directory.
+
+3. The `datastoreConnectOrCreate()` method will send these signed records to the Core node.
+The Core node replicates the root directory header (blue path), the root
+direcory payload (green path), and the datastore record (gold path).
+
+4. The Core node then replicates them with drivers `A`, `B`, and `C`.
+
+Now, storage systems `A`, `B`, and `C` each hold a copy of the datastore record
+and its root directory.
+
+*(Aside: The datastore record's consistency is preserved the same way as the
+inode consistency).*
+
+## Reading Data
+
+Once the application has a Core session token, a datastore private key, and a
+datastore connection object, it can proceed to read it. The available methods
+are:
+
+* `listDir()`: Get the contents of a directory
+
+* `getFile()`: Get the contents of a file
+
+* `stat()`: Get a file or directory's header
+
+Reading data is done by path, just as it is in UNIX. At a high-level, reading
+data involes (1) resolving the path to the inode, and (2) reading the inode's
+contents.
+
+Path resolution works as it does in UNIX: the root directory is fetched, then
+the first directory in the path, then the second directory, then the third
+directory, etc., until either the file or directory at the end of the path is
+fetched, or the name does not exist.
+
+### Authenticating Data
+
+Data authentication happens in the Core node,.
+This is meant to enable linking files and directories to legacy Web
+applications. For example, a user might upload a photo to a datastore, and
+create a public URL to it to share with friends who do not yet use Blockstack.
+
+By default, the Core node serves back the inode payload data
+(`application/octet-stream` for files, and `application/json` for directories).
+The application client may additionally request the signatures from the Core
+node if it wants to authenticate the data itself.
+
+### Path Resolution
+
+Applications do not need to do path resolution themselves; they simply ask the
+Blockstack Core node to do so on their behalf. Fetching the root directory
+works as follows:
+
+1. Get the root inode ID from the datastore record.
+
+2. Fetch all root inode headers.
+
+3. Select the latest inode header, and then fetch its payload.
+
+4. Authenticate the data.
+
+For example, if a client wanted to read the root directory, it would call
+`listDir()` with `"/"` as the path.
+
+![Gaia listdir](/docs/figures/gaia-listdir.png)
+
+The blue paths are the Core node fetching the root inode's headers. The green
+paths are the Core node selecting the latest header and fetching the root
+payload. The Core node would reply the list of inode names within the root
+directory.
+
+Once the root directory is resolved, the client simply walks down the path to
+the requested file or directory. This involves iteratively fetching a
+directory, searching its children for the next directory in the path, and if it
+is found, proceeding to fetch it.
+
+### Fetching Data
+
+Once the Core node has resolved the path to the base name, it looks up the inode
+ID from the parent directory and fetches it from the backend storage providers
+via the relevant drivers.
+
+For example, fetching the file `/bar` works as follows:
+
+![Gaia getFile](/docs/figures/gaia-getfile.png)
+
+1. Resolve the root directory (blue paths)
+
+2. Find `bar` in the root directory
+
+3. Get `bar`'s headers (green paths)
+
+4. Find the latest header for `bar`, and fetch its payload (gold paths)
+
+5. Return the contents of `bar`.
+
+## Writing Data
+
+There are three steps to writing data:
+
+* Resolving the path to the inode's parent directory
+
+* Creating and replicating the new inode
+
+* Linking the new inode to the parent directory, and uploading the new parent
+ directory.
+
+All of these are done with both `putFile()` and `mkdir()`.
+
+### Creating a New Inode
+
+When it calls either `putFile()` or `mkdir()`, the application client will
+generate a new inode header and payload and sign them with the datastore private
+key. Once it has done so successfully, it will insert the new inode's name and
+ID into the parent directory, give the parent directory a new version number,
+and sign and replicate it and its header.
+
+For example, suppose the client attempts to write the data `"hello world"` to `/bar`.
+To do so:
+
+![Gaia putFile](/docs/figures/gaia-putfile.png)
+
+1. The client executes `listDir()` on the parent directory, `/` (blue paths).
+
+2. If an inode by the name of `bar` exists in `/`, then the method fails.
+
+3. The client makes a new inode header and payload for `bar` and signs them with
+ the datastore private key. It replicates them to the datastore's storage
+drivers (green paths).
+
+4. The client adds a record for `bar` in `/`'s data obtained from (1),
+ increments the version for `/`, and signs and replicates `/`'s header and
+payload (gold paths).
+
+
+### Updating a File or Directory
+
+A client can call `putFile()` multiple times to set the file's contents. In
+this case, the client creates, signs, and replicates a new inode header and new
+inode payload for the file. It does not touch the parent directory at all.
+In this case, `putFile()` will only succeed if the parent directory lists an
+inode with the given name.
+
+A client cannot directly update the contents of a directory.
+
+## Deleting Data
+
+Deleting data can be done with either `rmdir()` (to remove an empty directory)
+or `deleteFile()` (to remove a file). In either case, the protocol executed is
+
+1. The client executes `listDir()` on the parent directory
+
+2. If an inode by the given name does not exist, then the method fails.
+
+3. The client removes the inode's name and ID from the directory listing, signs
+ the new directory, and replicates it to the Blockstack Core node.
+
+4. The client tells the Blockstack Core node to delete the inode's header and
+ payload from all storage systems.
+
+
+# Advanced Topics
+
+These features are still being implemented.
+
+## Data Integrity
+
+What happens if the client crashes while replicating new inode state? What
+happens if the client crashes while deleting inode state? The data hosted in
+the underlying data stores can become inconsistent with the directory structure.
+
+Given the choice between leaking data and rendering data unresolvable, Gaia
+chooses to leak data.
+
+### Partial Inode-creation Failures
+
+When creating a file or directory, Gaia stores four records in this order:
+
+* the new inode payload
+
+* the new inode header
+
+* the updated parent directory payload
+
+* the updated parent directory header
+
+If the new payload replicates successfully but the new header does not, then the
+new payload is leaked.
+
+If the new payload and new header replicate successfully, but neither parent
+directory record succeeds, then the new inode header and payload are leaked.
+
+If the new payload, new header, and updated parent directory payload replicate
+successfully, but the updated parent header fails, then not only are the new
+inode header and payload leaked, but also *reading the parent directory will
+fail due to a hash mismatch between its header and inode*. This can be detected
+and resolved by observing that the copy of the header in the parent directory
+payload has a later version than the parent directory header indicates.
+
+### Partial Inode-deletion Failures
+
+When deleting a file or directory, Gaia alters records in this order:
+
+* update parent directory payload
+
+* update parent directory header
+
+* delete inode header
+
+* delete inode payload
+
+Similar to partial failures from updating parent directories when creating
+files, if the client replicates the new parent directory inode payload but fails
+before it can update the header, then clients will detect on the next read that
+the updated payload is valid because it has a signed inode header with a newer
+version.
+
+If the client successfully updates the parent directory but fails to delete
+either the inode header or payload, then they are leaked. However, since the
+directory was updated, no correct client will access the deleted inode data.
+
+### Leak Recovery
+
+Gaia's storage drivers are designed to keep the inode data they store in a
+"self-contained" way (i.e. within a single folder or bucket). In the future,
+we will implement a `fsck`-like tool that will scan through a datastore and find
+the set of inode headers and payloads that are no longer referenced and delete
+them.
+
+## Multi-Device Support
+
+Contemporary users read and write data across multiple devices. In this
+document, we have thus far described datastores with the assumption that there
+is a single writer at all times.
+
+This assumption is still true in a multi-device setting, since a user is
+unlikely to be writing data with the same application simultaneously from two
+different devices.
+
+However, an open question is how multiple devices can access the same
+application data for a user. Our design goal is to **give each device its own
+keyring**, so if it gets lost, the user can revoke its access without having to
+re-key her other devices.
+
+To do so, we'll expand the definition of a datastore to be a **per-user,
+per-application, and per-device** collection of data. The view of a user's
+application data will be constructed by merging each device-specific
+datastore, and resolving conflicts by showing the "last-written" inode (where
+"last-written" is determined by a loosely-synchronized clock).
+
+For example, if a user uploads a profile picture from their phone, and then
+uploads a profile picture from their tablet, a subsequent read will query the
+phone-originated picture and the tablet-originated picture, and return the
+tablet-originated picture.
+
+The aforementioned protocols will need to be extended to search for inode
+headers not only on each storage provider, but also search for inodes on the
+same storage provider that may have been written by each of the user's devices.
+Without careful optimization, this can lead to a lot of inode header queries,
+which we address in the next topic.
+
+## A `.storage` Namespace
+
+Blockstack Core nodes can already serve as storage "gateways". That is, one
+node can ask another node to store its data and serve it back to any reader.
+
+For example, Alice can make her Blockstack Core node public and program it to
+store data to her Amazon S3 bucket and her Dropbox account. Bob can then post data to Alice's
+node, causing her node to replicate data to both providers. Later, Charlie can
+read Bob's data from Alice's node, causing Alice's node to fetch and serve back
+the data from her cloud storage. Neither Bob nor Charlie have to set up accounts on
+Amazon S3 and Dropbox this way.
+
+Since Alice is on the read/write path between Bob and Charlie and cloud storage,
+she has the opportunity to make optimizations. First, she can program her
+Core node to synchronously write data to
+local disk and asynchronously back it up to S3 and Dropbox. This would speed up
+Bob's writes, but at the cost of durability (i.e. Alice's node could crash
+before replicating to the cloud).
+
+In addition, Alice can program her Core node to service all reads from disk. This
+would speed up Charlie's reads, since he'll get the latest data without having
+to hit back-end cloud storage providers.
+
+Since Alice is providing a service to Bob and Charlie, she will want
+compensation. This can be achieved by having both of them send her money via
+the underlying blockchain.
+
+To do so, she would register her node's IP address in a
+`.storage` namespace in Blockstack, and post her rates per GB in her node's
+profile and her payment address. Once Bob and Charlie sent her payment, her
+node would begin accepting reads and writes from them up to the capacity
+purchased. They would continue sending payments as long as Alice provides them
+with service.
+
+Other experienced node operators would register their nodes in `.storage`, and
+compete for users by offerring better durability, availability, performance,
+extra storage features, and so on.
diff --git a/_core/attic/openbazaar.md b/_core/attic/openbazaar.md
new file mode 100644
index 00000000..2140592f
--- /dev/null
+++ b/_core/attic/openbazaar.md
@@ -0,0 +1,71 @@
+---
+layout: core
+permalink: /:collection/:path.html
+---
+# How to link your OpenBazaar GUID to your Blockstack ID
+{:.no_toc}
+* TOC
+{:toc}
+
+If you don't have the Blockstack CLI. Download and install it first. Instructions are [here](https://github.com/blockstack/blockstack-cli/blob/master/README.md). The rest of this tutorial assumes that you've already registered a name using the Blockstack CLI.
+
+## Step 1: Advanced Mode
+
+The first step is to activate "advanced mode" in the CLI. The command to do so is:
+
+```
+ $ blockstack set_advanced_mode on
+```
+
+## Step 2: Add an OpenBazaar Account
+
+The second step is to create an OpenBazaar account for your profile (the [Onename](https://onename.com) app also enabled to link your OpenBazaar GUID). The command to do so is:
+
+```
+ $ blockstack put_account "" "openbazaar" "" ""
+```
+
+The URL can be any valid URL; it won't be used by OpenBazaar. Here's an example, using the name `testregistration001.id` and the GUID `0123456789abcdef`:
+
+```
+ $ blockstack put_account "testregistration001.id" "openbazaar" "0123456789abcdef" "https://bazaarbay.org/@testregistration001"
+```
+
+The update should be instantaneous. You can verify that your store is present with `list_accounts`:
+
+```
+ $ blockstack list_accounts "testregistration001.id"
+ {
+ "accounts": [
+ {
+ "contentUrl": "https://bazaarbay.org/@testregistration001.id",
+ "identifier": "0123456789abcdef",
+ "service": "openbazaar"
+ }
+ ]
+ }
+````
+
+# Troubleshooting
+
+Common problems you might encounter.
+
+## Profile is in legacy format
+
+If you registered your blockstack ID before spring 2016, there's a chance that your profile is still in a legacy format. It will get migrated to the new format automatically if you update your profile on the [Onename](https://onename.com) app. However, you have to do this manually with the CLI.
+
+To do so, the command is:
+```
+ $ blockstack migrate
+```
+
+It will take a little over an hour to complete, but once finished, you'll be able to manage your accounts with the above commands (and do so with no delays).
+
+## Failed to broadcast update transaction
+
+This can happen during a `migrate` for one of a few reasons:
+* You do not have enough balance to pay the transaction fee (which is calculated dynamically).
+* Your payment address has unconfirmed transactions.
+* You can't connect to a Bitcoin node.
+
+To determine what's going on, you should try the command again by typing `BLOCKSTACK_DEBUG=1 blockstack ...` instead of `blockstack...`.
diff --git a/_core/attic/resolver.md b/_core/attic/resolver.md
new file mode 100644
index 00000000..50b00abb
--- /dev/null
+++ b/_core/attic/resolver.md
@@ -0,0 +1,33 @@
+# Blockstack Resolver
+
+During 2014-2016, Bockstack resolver was a separate service (like DNS resolvers).
+It was merged into the Blockstack API in early 2017.
+
+The following (legacy) API call is still being supported by the Blockstack API:
+
+```
+http://localhost:5000/v2/users/fredwilson
+```
+
+And you can see a legacy resolver in action at http://resolver.onename.com/v2/users/fredwilson
+
+## Cron Job for Namespaces
+
+**Note: the instructions below need updating.**
+
+Currently, the resolver indexes all valid names in a local file which can be
+populated by running
+> $ ./refresh_names.sh
+
+On a production deployment, you should add a crond job to periodically run this
+script. You can edit your crontab file by:
+> $ crontab -e
+
+Here is a sample crontab file that runs the refresh script every two hours:
+```
+SHELL=/bin/bash
+HOME=/home/ubuntu
+
+#This is a comment
+0 */2 * * * /home/ubuntu/resolver/resolver/refresh_names.sh
+```
diff --git a/_core/attic/tutorial_creation.md b/_core/attic/tutorial_creation.md
new file mode 100644
index 00000000..92851cb5
--- /dev/null
+++ b/_core/attic/tutorial_creation.md
@@ -0,0 +1,604 @@
+---
+layout: core
+permalink: /:collection/:path.html
+---
+# Create and Launch a Namespace
+{:.no_toc}
+
+This tutorial teaches you how to create your namespace, it contains the
+following sections:
+
+* TOC
+{:toc}
+
+
+Creating namespaces is expensive.
+Be sure to test your namespace in our [integration test
+framework](https://github.com/blockstack/blockstack-core/tree/master/integration_tests)
+first! It will let you simulate any valid namespace configuration
+you want at no risk to you.
+
+
+>**WARNING**: If you intend to create a namespace, you must read this document
+_in its entirety_. You should also _install the test framework_ and experiment
+with your namespace's parameters. _FAILURE TO DO SO MAY RESULT IN IRRECOVERABLE
+LOSS OF FUNDS._
+
+## Before you begin
+
+Some basic familiarity with how Bitcoin works is required to
+understand this tutorial. This includes:
+
+* knowing the difference between mainnet, testnet, and regtest
+* knowing about compressed and uncompressed ECDSA public keys
+* knowing about base58-check encoding
+* knowing how Bitcoin transactions are structured
+* knowing how UTXOs work
+
+Creating a namespace is a three-step process. The first step is to `preorder`
+the namespace, which broadcasts a salted hash of the namespace ID. The second
+step is to `reveal` the namespace, which exposes the namespace ID and price
+function to the blockchain. The final step is to `ready` the namespace, which
+allows anyone to register names within it.
+
+In between the `reveal` and `ready` steps, the namespace creator will have a
+"lock" on the namespace that lasts for about 1 year. During this time period,
+the namespace creator can `import` names. The `import` transaction lets the
+namespace creator assign the name a zone file and an owner in one step.
+
+## Before Trying This in Production...
+
+
+
+### Setting up the Test Environment
+
+In this example, we will use the test framework to create a private Bitcoin
+blockchain on your computer, and then create a Blockstack namespace on it.
+This will let you experiment with different namespace parameters
+without spending actual BTC. The test framework uses `bitcoind -regtest`,
+so all of the commands you'll run here will work identically on
+mainnet.
+
+To install the test framework, please follow these
+[instructions](https://github.com/blockstack/blockstack-core/tree/master/integration_tests).
+Once you have the test framework installed, you should run the `namespace_check` test in `--interactive-web` mode.
+This will create an empty `.test` namespace and leave the test scenario running
+once it finishes. You will be able to fund addresses and create new blocks via
+your Web browser or via `curl`, as will be explained below. Also, you'll be able to use the
+`blockstack` utility to interact with your private blockchain and namespaces.
+
+The test setup command is as follows. This will launch the `namespace_check`
+test scenario, and open a web server on port 3001.
+```bash
+ $ blockstack-test-scenario --interactive-web 3001 blockstack_integration_tests.scenarios.namespace_check
+```
+
+When the test is ready for us to experiment, you should see the following:
+
+```bash
+ An empty namespace called 'test' has been created
+ Feel free to experiment with other namespaces
+
+ Available keys with a balance:
+ * 6e50431b955fe73f079469b24f06480aee44e4519282686433195b3c4b5336ef01
+ * c244642ce0b4eb68da8e098facfcad889e3063c36a68b7951fb4c085de49df1b01
+ * f4c3907cb5769c28ff603c145db7fc39d7d26f69f726f8a7f995a40d3897bb5201
+ * 8f87d1ea26d03259371675ea3bd31231b67c5df0012c205c154764a124f5b8fe01
+ * bb68eda988e768132bc6c7ca73a87fb9b0918e9a38d3618b74099be25f7cab7d01
+ * 2,3,6f432642c087c2d12749284d841b02421259c4e8178f25b91542c026ae6ced6d01,65268e6267b14eb52dc1ccc500dc2624a6e37d0a98280f3275413eacb1d2915d01,cdabc10f1ff3410082448b708c0f860a948197d55fb612cb328d7a5cc07a6c8a01
+ * 2,3,4c3ab2a0704dfd9fdc319cff2c3629b72ebda1580316c7fddf9fad1baa323e9601,75c9f091aa4f0b1544a59e0fce274fb1ac29d7f7e1cd020b66f941e5d260617b01,d62af1329e541871b244c4a3c69459e8666c40b683ffdcb504aa4adc6a559a7701
+ * 2,3,4b396393ca030b21bc44a5eba1bb557d04be1bfe974cbebc7a2c82b4bdfba14101,d81d4ef8123852403123d416b0b4fb25bcf9fa80e12aadbc08ffde8c8084a88001,d0482fbe39abd9d9d5c7b21bb5baadb4d50188b684218429f3171da9de206bb201
+ * 2,3,836dc3ac46fbe2bcd379d36b977969e5b6ef4127e111f2d3e2e7fb6f0ff1612e01,1528cb864588a6a5d77eda548fe81efc44180982e180ecf4c812c6be9788c76a01,9955cfdac199b8451ccd63ec5377a93df852dc97ea01afc47db7f870a402ff0501
+```
+
+You can determine that the test framework is live by going to
+`http://localhost:3001` in your Web browser. From there, you can generate
+blocks in the test framework's `bitcoind` node and you can fund any address in
+the test framework.
+
+Finally, you can use the `blockstack-test-env` command to set up your shell
+environment variables so `blockstack` will interact with this test (instead of
+mainnet). To do so, run the following in your shell:
+
+```bash
+ $ . $(which blockstack-test-env) namespace_check
+ |blockstack-test namespace_check| $
+```
+
+You can verify that the environment variables by verifying that your `$PS1`
+variable includes the name of your test (as shown above), and that some other
+`BLOCKSTACK_`-prefixed variables are set:
+
+```bash
+ |blockstack-test namespace_check| $ env | grep BLOCKSTACK
+ BLOCKSTACK_OLD_PS1=\u@\h:\w$
+ BLOCKSTACK_TESTNET=1
+ BLOCKSTACK_EPOCH_1_END_BLOCK=1
+ BLOCKSTACK_EPOCH_2_END_BLOCK=2
+ BLOCKSTACK_TEST=1
+ BLOCKSTACK_DEBUG=1
+ BLOCKSTACK_CLIENT_CONFIG=/tmp/blockstack-run-scenario.blockstack_integration_tests.scenarios.namespace_check/client/client.ini
+```
+
+## Registering a Namespace
+
+Suppose we're going to create the `hello` namespace. The key
+`6e50431b955fe73f079469b24f06480aee44e4519282686433195b3c4b5336ef01` will be the key that
+*pays* for the namespace. The key
+`c244642ce0b4eb68da8e098facfcad889e3063c36a68b7951fb4c085de49df1b01` will be the key that
+*creates* the namespace. The creator key will be used to `import` names and
+declare the namespace `ready`. The payment key will be used to both pay for the
+namespace and receive name registration and renewal fees for the first year of
+the namespace's lifetime.
+
+In this example, we will set these keys as environment variables:
+
+```bash
+ |blockstack-test namespace_check| $ export PAYMENT_PKEY="6e50431b955fe73f079469b24f06480aee44e4519282686433195b3c4b5336ef01"
+ |blockstack-test namespace_check| $ export CREATOR_PKEY="c244642ce0b4eb68da8e098facfcad889e3063c36a68b7951fb4c085de49df1b01"
+```
+
+#### Multisig Namespace Payment
+
+If you want to use a multisig address to pay for your namespace (and collect
+name registration fees), then instead of using
+`6e50431b955fe73f079469b24f06480aee44e4519282686433195b3c4b5336ef01`, you should
+use a string formatted as `m,n,pk1,pk2,...,pk_n`. `m` is the number of
+signatures required, `n` is the number of private keys, and `pk1,pk2,...,pk_n`
+are the private keys.
+
+For example, you can use the following as your `PAYMENT_PKEY` to have a 2-of-3
+multisig script pay for your namespace and collect name registration fees:
+
+```bash
+ |blockstack-test namespace_check| $ export PAYMENT_PKEY="2,3,6f432642c087c2d12749284d841b02421259c4e8178f25b91542c026ae6ced6d01,65268e6267b14eb52dc1ccc500dc2624a6e37d0a98280f3275413eacb1d2915d01,cdabc10f1ff3410082448b708c0f860a948197d55fb612cb328d7a5cc07a6c8a01"
+```
+
+### Namespace preorder
+
+The command to preorder the namespace would be:
+
+```bash
+ |blockstack-test namespace_check| $ blockstack namespace_preorder hello "$PAYMENT_PKEY" "$CREATOR_PKEY"
+```
+
+You will be given a set of instructions on how to proceed to reveal and
+launch the namespace. _READ THEM CAREFULLY_. You will be prompted to
+explicitly acknowledge that you understand the main points of the instructions,
+and that you understand the risks.
+
+The command outputs some necessary information at the very end of its execution.
+In particular, you will need to remember the transaction ID of the namespace
+preorder. The command will help you do so.
+
+Here is a sample output:
+
+```bash
+ |blockstack-test namespace_check| $ blockstack namespace_preorder hello "$PAYMENT_PKEY" "$CREATOR_PKEY"
+
+ <...snip...>
+
+ Remember this transaction ID: b40dd1375ef63e5a40ee60d790ec6dccd06efcbac99d0cd5f3b07502a4ab05ac
+ You will need it for `blockstack namespace_reveal`
+
+ Wait until b40dd1375ef63e5a40ee60d790ec6dccd06efcbac99d0cd5f3b07502a4ab05ac has six (6) confirmations. Then, you can reveal `hello` with:
+
+ $ blockstack namespace_reveal "hello" "6e50431b955fe73f079469b24f06480aee44e4519282686433195b3c4b5336ef01" "c244642ce0b4eb68da8e098facfcad889e3063c36a68b7951fb4c085de49df1b01" "b40dd1375ef63e5a40ee60d790ec6dccd06efcbac99d0cd5f3b07502a4ab05ac"
+
+ {
+ "status": true,
+ "success": true,
+ "transaction_hash": "b40dd1375ef63e5a40ee60d790ec6dccd06efcbac99d0cd5f3b07502a4ab05ac"
+ }
+```
+
+If all goes well, you will get back a transaction hash (in this case, `b40dd1375ef63e5a40ee60d790ec6dccd06efcbac99d0cd5f3b07502a4ab05ac`).
+To get Blockstack to process it, you will need to mine some blocks in the test framework (by default,
+Blockstack will only accept a transaction that has 6 confirmations). To do
+this, simply go to `http://localhost:3001` and generate at least 6 blocks. If you
+observe the test log, you will see the Blockstack node process and accept it.
+
+Note that when you do this live, you should wait for
+at least 10 confirmations before sending the `reveal` transaction, just to be
+safe.
+
+### Namespace reveal
+
+The command to reveal a preordered namespace is more complicated, since it
+describes the price curve.
+
+This command is **interactive**. The command to invoke it is as follows:
+
+```bash
+ |blockstack-test namespace_check| $ blockstack namespace_reveal hello "$PAYMENT_PKEY" "$CREATOR_PKEY" "b40dd1375ef63e5a40ee60d790ec6dccd06efcbac99d0cd5f3b07502a4ab05ac"
+```
+
+When running the command, you will see the namespace creation wizard prompt you
+with the price curve and the current values:
+
+```
+Name lifetimes (blocks): infinite
+Price coefficient: 4
+Price base: 4
+Price bucket exponents: [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
+Non-alpha discount: 2
+No-vowel discount: 5
+Burn or receive fees? Receive to mr6nrMvvh44sR5MiX929mMXP5hqgaTr6fx
+
+Name price formula:
+(UNIT_COST = 10.0 satoshi):
+ buckets[min(len(name)-1, 15)]
+ UNIT_COST * coeff * base
+cost(name) = -----------------------------------------------------
+ max(nonalpha_discount, no_vowel_discount)
+
+
+Name price table:
+| length | price | price, nonalpha | price, no vowel | price, both |
+--------------------------------------------------------------------------
+| 1 | 42949672960 | 8589934592 | 8589934592 | 8589934592 |
+| 2 | 10737418240 | 5368709120 | 2147483648 | 2147483648 |
+| 3 | 2684354560 | 1342177280 | 536870912 | 536870912 |
+| 4 | 671088640 | 335544320 | 134217728 | 134217728 |
+| 5 | 167772160 | 83886080 | 33554432 | 33554432 |
+| 6 | 41943040 | 20971520 | 8388608 | 8388608 |
+| 7 | 10485760 | 5242880 | 2097152 | 2097152 |
+| 8 | 2621440 | 1310720 | 524288 | 524288 |
+| 9 | 655360 | 327680 | 131072 | 131072 |
+| 10 | 163840 | 81920 | 32768 | 32768 |
+| 11 | 40960 | 20480 | 8192 | 8192 |
+| 12 | 10240 | 5120 | 2048 | 2048 |
+| 13 | 2560 | 1280 | 512 | 512 |
+| 14 | 640 | 320 | 128 | 128 |
+| 15 | 160 | 80 | 32 | 32 |
+| 16+ | 40 | 20 | 10 | 10 |
+
+
+What would you like to do?
+(0) Set name lifetime in blocks (positive integer between 1 and 4294967295, or "infinite")
+(1) Set price coefficient (positive integer between 1 and 255)
+(2) Set base price (positive integer between 1 and 255)
+(3) Set price bucket exponents (16 comma-separated integers, each between 1 and 15)
+(4) Set non-alphanumeric character discount (positive integer between 1 and 15)
+(5) Set no-vowel discount (positive integer between 1 and 15)
+(6) Toggle collecting name fees (True: receive fees; False: burn fees)
+(7) Show name price formula
+(8) Show price table
+(9) Done
+
+(1-9)
+```
+
+All prices are in the "fundamental unit" of the underlying blockchain (i.e.
+satoshis).
+
+As the formula describes, the name's price is a function of:
+
+* a fixed unit cost (`UNIT_COST`)
+* a multiplicative constant coefficient (`coeff`)
+* a fixed exponential base (`base`)
+* a 16-element list of price buckets, indexed by the length of the name (`buckets`)
+* a discount for having non-alphnumeric letters (`nonalpha_discount`)
+* a discount for having no vowels in the name (`no_vowel_discount`)
+
+You can use options 1 through 8 to play with the pricing function and examine
+the name costs in the price table. Enter 9 to send the transaction itself.
+
+Once you're happy, you can issue the namespace-reveal transaction. As with the
+namespace-preorder transaction, you will get back a transaction hash, and your transaction will be
+unconfirmed. Simply go to `http://localhost:3001` to generate some more blocks
+to confirm your namespace-reveal.
+
+Once you have confirmed your namespace-reveal transaction, you can
+begin to populate your namespace with some initial names.
+
+**Collecting Name Fees**
+
+Blockstack 0.17 introduced the ability to create a namespace such that for the
+first year of its existence (54595 blocks), all name registration and renewal
+fees will be sent to the address of the _payment key_. In this example,
+this is the address `mr6nrMvvh44sR5MiX929mMXP5hqgaTr6fx`.
+
+The alternative is to
+have all namespace fees sent to an unspendable burn address
+(`1111111111111111111114oLvT2`). This is the case for the `.id` namespace,
+for example.
+
+After the year has passed, all future name registrations and renewal fees
+will be sent to the unspendable burn address. This is to disincentivize
+namespace squatters.
+
+**Warnings**
+
+* You must issue this command **within 144 blocks** of the namespace-preorder transaction. Otherwise, the preorder will expire and you will need to start over from scratch.
+
+### Importing names
+
+After sending the `reveal` transaction, you can populate your namespace with
+some initial names. You can do so with the `name_import` command.
+
+Suppose we want to import the name `example.hello` and assign it to an owner
+whose public key address is `ms6Y32bcL5zhA57e8tf7awgVZuPxV8Xg8N`. Suppose also
+that you wanted to give `example.hello` an initial zone file stored at
+`/var/blockstack/zone_files/example.hello`. To do so, you would issue the
+following command:
+
+```bash
+ |blockstack-test namespace_check| $ blockstack name_import example.hello ms6Y32bcL5zhA57e8tf7awgVZuPxV8Xg8N /var/blockstack/zone_files/example.hello "$CREATOR_PKEY"
+```
+
+By default, you **must** use the private key you used to reveal the namespace
+to import names (this is `$CREATOR_PKEY` in this example).
+
+As with namespace-preorder and namespace-reveal, the transaction this command
+generates will be unconfirmed. Simply go to `http://localhost:3001` to generate
+some blocks to confirm it.
+
+You can check the progress of the transaction with `blockstack info`, as follows:
+
+```bash
+ |blockstack-test namespace_check| $ blockstack info
+ {
+ "cli_version": "0.17.0.8",
+ "consensus_hash": "b10fdd38a20a7e46555ce3a7f68cf95c",
+ "last_block_processed": 694,
+ "last_block_seen": 694,
+ "queues": {
+ "name_import": [
+ {
+ "confirmations": 1,
+ "name": "example.hello",
+ "tx_hash": "10f7dcd9d6963ef5d20d010f731d5d2ddb76163a083b9d7a2b9fd4515c7fe58c"
+ }
+ ]
+ },
+ "server_alive": true,
+ "server_host": "localhost",
+ "server_port": 16264,
+ "server_version": "0.17.0.8"
+ }
+```
+
+The `confirmation` field indicates how deep in the blockchain the transaction is
+at the time. Generating more blocks will increase its number of confirmations.
+
+When you do this live,
+**YOU SHOULD LEAVE YOUR COMPUTER RUNNING UNTIL THE `name_import` QUEUE IS EMPTY**.
+Blockstack's background API daemon will monitor the transactions and upload the
+name's zone file to the Blockstack Atlas network once it is confirmed.
+But to do so, your computer must remain online. If you do not do this, then
+the name will not have a zone file and will be unusable in the higher layers of
+Blockstack-powered software (including Blockstack applications). However,
+if your computer does go offline or reboots, you can recover by
+restarting the Blockstack API daemon (with
+`blockstack api start`). The daemon itself will pick up where it left off, and
+replicate all zone files that have confirmed transactions.
+
+After the zone file is uploaded, the name will be public and resolvable. You can re-import the
+same name over and over, and give it a different address and/or zone file. Like
+all other names, the Blockstack Atlas network will accept and propagate zone
+files for imported names.
+
+The owner of the address `ms6Y32bcL5zhA57e8tf7awgVZuPxV8Xg8N` will **not** be
+able to issue any transactions for the name `example.hello` until the namespace
+creator has sent the `ready` transaction.
+
+#### Using multiple private keys for NAME_IMPORT
+
+Bitcoin itself imposes limits on how fast you can send transactions from the
+same key (limited by a maximum UTXO-chain length). To work around this,
+Blockstack lets you import names by using up to 300 private keys. The private
+keys you can use are BIP32 unhardened children of the namespace reveal key (i.e.
+`$CREATOR_PKEY` in this example).
+
+The first name you import **must** use the namespace reveal private key
+(`$CREATOR_PKEY` in this example). However, all future names you import in this
+namespace can use one of the 300 BIP32 keys.
+
+To get the list of keys you can use, you can use the `make_import_keys` command:
+
+```bash
+ |blockstack-test namespace_check| $ blockstack make_import_keys example hello "$CREATOR_PKEY"
+ aeda50305ada40aaf53f2d8921aa717f1ec71a0a3b9b4c6397b3877f6d45c46501 (n4DVTuLLv5J1Yc17AoRYY1GtxDAuLGAESr)
+ 92ff179901819a1ec7d32997ce3bb0d9a913895d5850cc05146722847128549201 (mib2KNBGR4az8GiUmusBZexVBqb9YB2gm5)
+ cc5b6a454e2b614bfa18f4deb9a8e179ab985634d63b7fedfaa59573472d209b01 (mxE2iqV4jdpn4K349Gy424TvZp6MPqSXve)
+ 9b0265e0ac8c3c24fe1d79a734b3661ec2b5c0c2619bb6342356572b8235910101 (n4rGz8hkXTscUGWCwZvahrkEh6LHZVQUoa)
+ e2585af250404b7918cf6c91c6fa67f3401c0d1ae66df2fafa8fa132f4b9350f01 (moGNpEpighqc6FnkqyNVJA9xtfTiStr5YU)
+ {
+ "status": true
+ }
+```
+
+(NOTE: in the test environment, you get only 5 keys in order to save time).
+
+You can use any of these keys to import names.
+
+#### Trying it out
+
+Here's an example walkthrough of how to try this out in the test framework:
+
+1. Import the first name, creating a zone file in the process:
+
+```bash
+ |blockstack-test namespace_check| $ cat > /var/blockstack/zone_files/example.hello < $ORIGIN example.hello
+ > $TTL 3600
+ > _file URI 10 1 "file:///home/blockstack-test/example.hello"
+ > EOF
+ |blockstack-test namespace_check| $ blockstack name_import example.hello ms6Y32bcL5zhA57e8tf7awgVZuPxV8Xg8N /var/blockstack/zone_files/example.hello "$CREATOR_PKEY"
+ Import cost breakdown:
+ {
+ "name_import_tx_fee": {
+ "btc": 0.0003342,
+ "satoshis": 33420
+ },
+ "total_estimated_cost": {
+ "btc": 0.0003342,
+ "satoshis": 33420
+ },
+ "total_tx_fees": 33420
+ }
+ Importing name 'example.hello' to be owned by 'ms6Y32bcL5zhA57e8tf7awgVZuPxV8Xg8N' with zone file hash '05c302430f4ed0a24470abf9df7e264d517fd389'
+ Proceed? (y/N) y
+ {
+ "status": true,
+ "success": true,
+ "transaction_hash": "bd875f00f63bcb718bb22782c88c3edcbed79663f2f9152deab328c48746f103",
+ "value_hash": "05c302430f4ed0a24470abf9df7e264d517fd389"
+ }
+```
+
+2. Advance the test framework blockchain, so the indexer knows which import keys to expect:
+
+```bash
+ # NOTE: you can also do this by going to http://localhost:3001 in your Web browser
+ |blockstack-test namespace_check| $ curl -X POST http://localhost:3001/nextblock
+```
+
+3. Make import keys:
+
+```bash
+ |blockstack-test namespace_check| $ blocksatck make_import_keys hello "$CREATOR_PKEY"
+ aeda50305ada40aaf53f2d8921aa717f1ec71a0a3b9b4c6397b3877f6d45c46501 (n4DVTuLLv5J1Yc17AoRYY1GtxDAuLGAESr)
+ 92ff179901819a1ec7d32997ce3bb0d9a913895d5850cc05146722847128549201 (mib2KNBGR4az8GiUmusBZexVBqb9YB2gm5)
+ cc5b6a454e2b614bfa18f4deb9a8e179ab985634d63b7fedfaa59573472d209b01 (mxE2iqV4jdpn4K349Gy424TvZp6MPqSXve)
+ 9b0265e0ac8c3c24fe1d79a734b3661ec2b5c0c2619bb6342356572b8235910101 (n4rGz8hkXTscUGWCwZvahrkEh6LHZVQUoa)
+ e2585af250404b7918cf6c91c6fa67f3401c0d1ae66df2fafa8fa132f4b9350f01 (moGNpEpighqc6FnkqyNVJA9xtfTiStr5YU)
+ {
+ "status": true
+ }
+```
+
+4. Fill up one of the addresses in the test framework, so we can fund `NAME_IMPORT` transactions with it:
+
+```bash
+ # NOTE: you can also do this by going to http://localhost:3001 in your Web browser
+ |blockstack-test namespace_check| $ curl -X POST -F 'addr=n4DVTuLLv5J1Yc17AoRYY1GtxDAuLGAESr' -F 'value=100000000' 'http://localhost:3001/sendfunds'
+```
+
+5. Import another name, with the child private key we just funded:
+
+```bash
+ |blockstack-test namespace_check| $ cat > /tmp/example.hello.zonefile < $ORIGIN example2.hello
+ > $TTL 3600
+ > _file URI 10 1 "file:///home/blockstack-test/example2.hello"
+ > EOF
+ |blockstack-test namespace_check| $ blockstack name_import example2.hello n3sFkNfBQPWS25G12DqDEqHRPiqHotAkEb /tmp/example.hello.zonefile aeda50305ada40aaf53f2d8921aa717f1ec71a0a3b9b4c6397b3877f6d45c46501
+ Import cost breakdown:
+ {
+ "name_import_tx_fee": {
+ "btc": 0.0003342,
+ "satoshis": 33420
+ },
+ "total_estimated_cost": {
+ "btc": 0.0003342,
+ "satoshis": 33420
+ },
+ "total_tx_fees": 33420
+ }
+ Importing name 'example2.hello' to be owned by 'n3sFkNfBQPWS25G12DqDEqHRPiqHotAkEb' with zone file hash '0649bc0b457f54c564d054ce20dc3745a0c4f0c0'
+ Proceed? (y/N) y
+ {
+ "status": true,
+ "success": true,
+ "transaction_hash": "496a6c2aaccedd98a8403c2e61ff3bdeff221a58bf0e9c362fcae981353f459f",
+ "value_hash": "0649bc0b457f54c564d054ce20dc3745a0c4f0c0"
+ }
+```
+
+6. Advance the blockchain again:
+
+```bash
+ # NOTE: you can also do this by going to http://localhost:3001 in your Web browser
+ |blockstack-test namespace_check| $ curl -X POST http://localhost:3001/nextblock
+```
+
+7. See that the names are processing:
+
+```bash
+ |blockstack-test namespace_check| $ blockstack info
+ {
+ "cli_version": "0.17.0.8",
+ "consensus_hash": "2a055beeaedcaa1365ab2671a0254a03",
+ "last_block_processed": 711,
+ "last_block_seen": 711,
+ "queues": {
+ "name_import": [
+ {
+ "confirmations": 2,
+ "name": "example.hello",
+ "tx_hash": "bd875f00f63bcb718bb22782c88c3edcbed79663f2f9152deab328c48746f103",
+ },
+ {
+ "confirmations": 1,
+ "name": "example2.hello",
+ "tx_hash": "496a6c2aaccedd98a8403c2e61ff3bdeff221a58bf0e9c362fcae981353f459f"
+ }
+ ]
+ },
+ "server_alive": true,
+ "server_host": "localhost",
+ "server_port": 16264,
+ "server_version": "0.17.0.8"
+ }
+```
+
+8. Confirm all the transactions:
+
+```bash
+ # NOTE: you can also do this by going to http://localhost:3001 in your Web browser
+ |blockstack-test namespace_check| $ for i in $(seq 1 10); do curl -X POST http://localhost:3001/nextblock
+```
+
+9. Look up name zone files to confirm they were replicated to the test framework's Atlas network:
+
+```bash
+ |blockstack-test namespace_check| $ blockstack info
+ {
+ "cli_version": "0.17.0.8",
+ "consensus_hash": "ad247c1d5ff239a65db0736951078f17",
+ "last_block_processed": 721,
+ "last_block_seen": 721,
+ "queues": {},
+ "server_alive": true,
+ "server_host": "localhost",
+ "server_port": 16264,
+ "server_version": "0.17.0.8"
+ }
+ |blockstack-test namespace_check| $ blockstack get_name_zonefile example.hello
+ $ORIGIN example.hello
+ $TTL 3600
+ _file URI 10 1 "file:///home/blockstack-test/example.hello"
+
+ |blockstack-test namespace_check| $ blockstack get_name_zonefile example2.hello
+ $ORIGIN example2.hello
+ $TTL 3600
+ _file URI 10 1 "file:///home/blockstack-test/example2.hello"
+```
+
+Now, these names are imported and once the `NAMESPACE_READY` transaction is
+sent, the name owners can proceed to issue name operations.
+
+**Warnings**
+
+* The first private key you use must be the same one you used to *create* the namespace (`$CREATOR_KEY`).
+* You may only use the 300 private keys described above to import names.
+* You must complete all `NAME_IMPORT` transactions within 52595 blocks of the `NAMESPACE_REVEAL` transaction (about 1 year).
+
+### Launching a Namespace
+
+Once you have pre-populated your namespace with all of the initial names, you
+have to make it `ready` so anyone can register a name. If you do not do this
+within 1 year of the `reveal` transaction, then your namespace and all of the
+names will disappear, and someone else will be able to register it.
+
+To make a namespace `ready`, you use the creator private key as follows:
+
+```bash
+ |blockstack-test namespace_check| $ blockstack namespace_ready hello "$CREATOR_PKEY"
+```
+
+**Warnings**
+
+* You must send the `NAMESPACE_READY` transaction within 52595 blocks (about 1 year) of the `NAMESPACE_REVEAL` transaction.
diff --git a/_core/basic_usage.md b/_core/basic_usage.md
new file mode 100644
index 00000000..ecdb12ac
--- /dev/null
+++ b/_core/basic_usage.md
@@ -0,0 +1 @@
+The documentation has been moved to [docs.blockstack.org](https://docs.blockstack.org/), please update your bookmarks.
diff --git a/_core/best-practices.md b/_core/best-practices.md
new file mode 100644
index 00000000..feffd68f
--- /dev/null
+++ b/_core/best-practices.md
@@ -0,0 +1,47 @@
+## Hardware and OS requirements
+
+* A 64-bit CPU running at at least 1 GHz is *highly* recommended (but not strictly required)
+* You will need ~250MB RAM and ~10 GB disk free. Do **not** attempt to use a network-attached disk for this.
+* You should have at least 30,000 inodes free in your filesystem. Unless you are using a very small VM image, you almost certainly have enough (you can check with `df -i`).
+* TCP port 6264 should be open and support bidirectional traffic. If you want to use SSL, then port 6263 should be open.
+* A reliable Internet connection of DSL-like quality or higher
+
+## Deployment
+### The Easy Way
+* Install from `pip`, source code, or Docker
+* Run `blockstack-core fast_sync`
+* Run `blockstack-core start`
+
+### The Less Easy Way
+* Install from `pip`, source code, or Docker
+* Run `blockstack-core start`
+* Wait a few days
+
+#### Best Practices for the Less Easy Way
+* Take a `blockstack-server.snapshots` database from a known-good node and pass `--expected_snapshots=/path/to/blockstack-server.snapshots`. This will force your bootstrapping node to verify that it reaches the same sequence of consensus hashes as it bootstraps (i.e. your node will detect any divergence from Blockstack's name history and abort early, instead of wasting your time).
+* Make sure you're in a position to leave the node online at 100% CPU use for the duration of its bootstrapping period
+
+### The Hard Way
+* Install `bitcoind` (version 0.16.x is recommended for now)
+* Start `bitcoind` as `bitcoind -daemon -txindex=1`
+* Wait for `bitcoind` to download the entire blockchain. This can take between 1 hour and 1 day.
+* Install `blockstack-core` from source, `pip`, or Docker
+* Run `blockstack-core configure` and enter your `bitcoind` node's IP address, port, RPC username, and RPC password when prompted
+* Run `blockstack-core start`
+* Wait a few days
+
+#### Best Practices for the Hard Way
+* You're going to need ~500 GB of space for the Bitcoin blockchain state
+* You can safely store its chain state on a network-attached disk, if you're doing this in a cloud-hosted environment
+* Your `bitcoind` host will need TCP:8332-8333 open for bidirectional traffic
+
+## Troubleshooting
+### The node stops responding to TCP:6264
+* Check `dmesg` for TCP SYN flooding. The solution here is to kill and restart the node.
+* To mitigate, install a rate-limiting proxy HTTP server in front of the node. We have a sample config for `nginx` [here](https://github.com/blockstack/atlas/blob/master/public_fleet/node/default).
+
+### No other Blockstack nodes contact my node
+* Verify that your IP address is publicly-routable, and that peers can communicate on TCP:6264
+
+### People are attacking my Bitcoin node
+* Stick an `nginx` reverse proxy in front of your `bitcoind` node, and use our [nginx](https://github.com/blockstack/atlas/tree/master/public_fleet/bitcoind) scripts to limit APi access to only the JSON-RPC methods Blockstack actually needs. Better yet, do what we do---build a statically-linked `bitcoind` binary from source that simply omits all of the RPC methods except the ones listed in the linked config file.
diff --git a/_core/blockstack_naming_service.md b/_core/blockstack_naming_service.md
new file mode 100644
index 00000000..ecdb12ac
--- /dev/null
+++ b/_core/blockstack_naming_service.md
@@ -0,0 +1 @@
+The documentation has been moved to [docs.blockstack.org](https://docs.blockstack.org/), please update your bookmarks.
diff --git a/_core/cli.md b/_core/cli.md
new file mode 100644
index 00000000..ecdb12ac
--- /dev/null
+++ b/_core/cli.md
@@ -0,0 +1 @@
+The documentation has been moved to [docs.blockstack.org](https://docs.blockstack.org/), please update your bookmarks.
diff --git a/_core/faq_developer.md b/_core/faq_developer.md
new file mode 100644
index 00000000..190ee50f
--- /dev/null
+++ b/_core/faq_developer.md
@@ -0,0 +1,142 @@
+---
+layout: learn
+permalink: /:collection/:path.html
+---
+# Developer FAQs
+{:.no_toc}
+
+These FAQs are intended for developers of Blockstack.
+
+* TOC
+{:toc}
+
+
+## I'm a web developer. Can I build on Blockstack?
+
+Yes! Blockstack is geared primarily towards web developers. All of your
+existing knowledge is immediately applicable to Blockstack. Anything you can do
+in a web browser, you can do in a Blockstack app.
+
+## I'm a non-web developer. Can I build on Blockstack?
+
+Yes! Blockstack implements a [RESTful API](https://core.blockstack.org) which
+lets you interact with Blockstack from any language and any runtime. In fact,
+the reference client
+([blockstack.js](https://github.com/blockstack/blockstack.js)) is mainly a
+wrapper around these RESTful API calls, so you won't be missing much by using a
+language other than Javascript.
+
+## What's the difference between a web app and a Blockstack app?
+
+Blockstack apps are built like [single-page web
+apps](https://en.wikipedia.org/wiki/Single-page_application)--- they are, in
+fact, a type of web application.
+
+Blockstack apps are a subset of web applications that use Blockstack's
+technology to preserve the user's control over their identities and data. As
+such, they tend to be simple in design and operation, since in many cases they
+don't have to host anything besides the application's assets.
+
+## Do I need to learn any new languages or frameworks?
+
+No. Blockstack applications are built using existing web frameworks and programming
+The only new thing you need to learn is either [blockstack.js](https://github.com/blockstack/blockstack.js) or
+the [Blockstack RESTful API](https://core.blockstack.org).
+
+## How does my web app interact with Blockstack?
+
+The [blockstack.js](https://github.com/blockstack/blockstack.js) library gives
+any web application the ability to interact with Blockstack's authentication and
+storage services. In addition, we supply a [public RESTful API](https://core.blockstack.org).
+
+## What does `blockstack.js` do?
+
+This is the reference client implementation for Blockstack. You use it in your
+web app to do the following:
+
+* Authenticate users
+* Load and store user data
+* Read other users' public data
+
+## How do I use `blockstack.js`?
+
+We have [several examples](/browser/hello-blockstack.html) you can use to get started. Please see the API documentation [here](https://github.com/blockstack/blockstack.js).
+
+## How can I look up names and profiles?
+
+You can use `blockstack.js`, or you can use the [public Blockstack Core
+endpoint](https://core.blockstack.org).
+
+## How can I read my public app data without `blockstack.js`?
+
+The URLs to a user's public app data are in a canonical location in their
+profile. For example, here's how you would get public data from the
+[Publik](https://publik.ykliao.com) app, stored under the Blockstack ID `ryan.id`.
+
+1. Get the bucket URL
+```bash
+$ BUCKET_URL="$(curl -sL https://core.blockstack.org/v1/users/ryan.id | jq -r '."ryan.id"["profile"]["apps"]["http://publik.ykliao.com"]')"
+$ echo "$BUCKET_URL"
+https://gaia.blockstack.org/hub/1FrZTGQ8DM9TMPfGXtXMUvt2NNebLiSzad/
+```
+
+2. Get the data
+```bash
+$ curl -sL "${BUCKET_URL%%/}/statuses.json"
+[{"id":0,"text":"Hello, Blockstack!","created_at":1515786983492}]
+```
+
+## How do I register Blockstack IDs?
+
+You should use the [Blockstack Browser](https://github.com/blockstack/blockstack-browser).
+
+## How do I register Blockstack Subdomains?
+
+You can deploy and use a [Blockstack Subdomain Registrar]({{ site.baseurl }}/core/naming/subdomains.html), or
+use an existing one.
+
+## Can I programmatically register Blockstack IDs?
+
+Blockstack applications do not currently have
+have access to the user's wallet. Users are expected to
+register Blockstack IDs themselves.
+
+However, if you feel particularly ambitious, you can do one of the following:
+
+* Set up a `blockstack api` endpoint (see the project [README](https://github.com/blockstack/blockstack-core/blob/master/README.md)) and write a
+ program to automatically register names. Also, see the [API
+documentation](https://core.blockstack.org//#managing-names-register-a-name)
+for registering names on this endpoint.
+
+* Write a `node.js` program that uses `blockstack.js` to register
+ names. This is currently in development.
+
+## Can I programmatically register Blockstack Subdomains?
+
+Yes! Once you deploy your own subdomain registrar, you can have your web app
+send it requests to register subdomains on your Blockstack ID. You can also
+create a program that drives subdomain registration on your Blockstack ID.
+
+## Do you have a testnet or sandbox to experiment with Blockstack?
+
+We have an [integration test framework](https://github.com/blockstack/blockstack-core/tree/master/integration_tests) that provides a
+private Blockstack testnet. It uses `bitcoin -regtest` to create a private
+blockchain that you can interact with, without having to spend any Bitcoin or
+having to wait for blocks to confirm. Please see the
+[README](https://github.com/blockstack/blockstack-core/blob/master/integration_tests/README.md) for details.
+
+## Does Blockstack have a smart contract system?
+
+No, not yet. This is because
+Blockstack's design philosophy focuses on keeping system complexity at the
+"edges" of the network (e.g. clients), instead of the "core" of the network (e.g.
+the blockchain), in accordance with the [end-to-end
+principle](https://en.wikipedia.org/wiki/End-to-end_principle).
+Generally speaking, this can be interpreted as "if you can do X without
+a smart contract, you should do X without a smart contract." This organizing
+principle applies to a lot of useful decentralized applications.
+
+## Can Blockstack applications interact with Bitcoin? Ethereum? Smart contracts? Other blockchains?
+
+Yes! Since Blockstack applications are built like web applications, all you need to do is include the
+relevant Javascript library into your application.
diff --git a/_core/faq_evaluators.md b/_core/faq_evaluators.md
new file mode 100644
index 00000000..5e14be31
--- /dev/null
+++ b/_core/faq_evaluators.md
@@ -0,0 +1,148 @@
+## What is the Blockstack ecosystem
+
+In the Blockstack ecosystem, users control their data and apps run on their devices. There
+are no middlemen, no passwords, no massive data silos to breach, and no services
+tracking us around the internet.
+
+The applications on blockstack are server-less and decentralized. Developers
+start by building a single-page application in Javascript, Then, instead of
+plugging the frontend into a centralized API, they plug into an API run by the
+user. Developers install a library called `blockstack.js` and don't have to
+worry about running servers, maintaining databases, or building out user
+management systems.
+
+Personal user APIs ship with the Blockstack app and handle everything from
+identity and authentication to data storage. Applications can request
+permissions from users and then gain read and write access to user resources.
+
+Data storage is simple and reliable and uses existing cloud infrastructure.
+Users connect with their Dropbox, Google Drive, S3, etc... and data is synced
+from their local device up to their cloud.
+
+Identity is user-controlled and utilizes the blockchain for secure management of
+keys, devices and usernames. When users login with apps, they are anonymous by
+default and use an app-specific key, but their full identity can be revealed and
+proven at any time. Keys are for signing and encryption and can be changed as
+devices need to be added or removed.
+
+Under the hood, Blockstack provides a decentralized domain name system (DNS),
+decentralized public key distribution system, and registry for apps and user
+identities.
+
+## What problems does Blockstack solve?
+
+Developers can now build Web applications where:
+
+- you own your data, not the application
+- you control where your data is stored
+- you control who can access your data
+
+Developers can now build Web applications where:
+
+- you don't have to deal with passwords
+- you don't have to host everyone's data
+- you don't have to run app-specific servers
+
+Right now, Web application users are "digital serfs" and applications are the "digital landlords". Users don't own their data; the app owns it. Users don't control where data gets stored; they can only store it on the application. Users don't control access to it; they only advise the application on how to control access (which the application can ignore).
+
+Blockstack applications solve both sets of problems. Users pick and choose highly-available storage providers like Dropbox or BitTorrent to host their data, and applications read it with the user's consent. Blockstack ensures that all data is signed and verified and (optionally) encrypted end-to-end, so users can treat storage providers like dumb hard drives: if you don't like yours, you can swap it out with a better one. Users can take their data with them if they leave the application, since it was never the application's in the first place.
+
+At the same time, developers are no longer on the hook for hosting user data. Since users bring their own storage and use public-key cryptography for authentication, applications don't have to store anything--there's nothing to steal when they get hacked. Moreover, many Web applications today can be re-factored so that everything happens client-side, obviating the need for running dedicated application servers.
+
+
+## What is a Blockstack ID?
+
+Blockstack IDs are usernames. Unlike normal Web app usernames, Blockstack IDs
+are usable *across every Blockstack app.* They fill a similar role to
+centralized single-signon services like Facebook or Google. However, you and
+only you control your Blockstack ID, and no one can track your logins.
+
+## How do I get a Blockstack ID?
+
+If you use the [Blockstack Browser]({{ site.baseurl }}/browser/browser-introduction.html) to create a
+new ID.
+
+## Why do I need a Blockstack ID?
+
+Blockstack IDs are used to discover where you are keeping your
+(publicly-readable) application data. For example, if `alice.id` wants to share
+a document with `bob.id`, then `bob.id`'s browser uses the Blockstack ID
+`alice.id` to look up where `alice.id` stored it.
+
+The technical descriptions of how and why this works are quite long.
+Please see the [Blockstack Naming Service]({{site.baseurl}}/core/naming/introduction.html)
+documentation for a full description.
+
+=
+
+## What components make ups the Blockstack ecosystem?
+
+The components that make up Blockstack do not have any central points of
+control.
+
+* The [Blockstack Naming Service]({{ site.baseurl }}/core/naming/introduction.html) runs on top of
+ the Bitcoin blockchain, which itself is decentralized. It binds Blockstack
+IDs to a small amount of on-chain data (usually a hash of off-chain data).
+* The [Atlas Peer Network]({{ site.baseurl }}/core/atlas/overview.html) stores chunks of data referenced by
+names in BNS. It operates under similar design principles to BitTorrent, and
+has no single points of failure. The network is self-healing---if a node
+crashes, it quickly recovers all of its state from its peers.
+* The [Gaia storage system](https://github.com/blockstack/gaia) lets users
+ choose where their application data gets hosted. Gaia reduces all storage
+systems---from cloud storage to peer-to-peer networks---to dumb, interchangeable
+hard drives. Users have maximum flexibility and control over their data in a
+way that is transparent to app developers.
+
+
+## Blockstack vs Ethereum
+
+Blockstack and Ethereum both strive to provide a decentralized application
+platform. Blockstack's design philosophy differs from Ethereum's design
+philosophy in that Blockstack emphasizes treating the blockchain as a "dumb
+ledger" with no special functionality or properties beyond a few bare minimum
+requirements. Instead, it strives to do everything off-chain---an application of the [end-to-end principle](https://en.wikipedia.org/wiki/End-to-end_principle).
+Most Blockstack applications do *not*
+interact with the blockchain, and instead interact with Blockstack
+infrastructure through client libraries and RESTful endpoints.
+This is evidenced by Blockstack's decision to implement its naming system (BNS), discovery and routing system
+(Atlas), and storage system (Gaia) as blockchain-agnostic components that can be
+ported from one blockchain to another.
+
+Ethereum takes the opposite approach. Ethereum dapps are expected to interface
+directly with on-chain smart contract logic, and are expected to host a
+non-trivial amount of state in the blockchain itself. This is necessary for
+them, because many Ethereum dapps' business logic is centered around the
+mechanics of an ERC20 token.
+
+Blockstack does not implement a smart contract system (yet), but it will soon
+implement a [native token](https://blockstack.com/distribution.pdf) that will be
+accessible to Blockstack applications.
+
+
+## What's the difference between Onename and Blockstack?
+
+Onename is the free Blockstack ID registrar run by Blockstack. It makes it easy to register your name and setup your profile. Once the name has been registered in Onename you can transfer it to a wallet you control, or leave it there and use it as you like.
+
+## How is Blockstack different from Namecoin?
+
+Blockstack DNS differs from Namecoin DNS in a few fundamental ways: blockchain layering, storage models, name pricing models, and incentives for miners. We wrote a post where you can learn more here: https://blockstack.org/docs/blockstack-vs-namecoin
+
+## I heard you guys were on Namecoin, what blockchain do you use now?
+
+We use the Bitcoin blockchain for our source of truth.
+
+## How long has the project been around?
+
+Work on the project started in late 2013. First public commits on the code are
+from Jan 2014. The first registrar for Blockstack was launched in March 2014 and
+the project has been growing since then.
+
+## Who started the project? Who maintains it?
+
+The project was started by two engineers from Princeton University. Muneeb Ali
+and Ryan Shea met at the Computer Science department at Princeton, where Muneeb
+was finishing his PhD and Ryan was running the enterprenurship club. In 2014,
+frustrated by the walled-gardens and security problems of the current internet
+they started working on a decentralized internet secured by blockchains. A full
+list of contributors can be found
+[here](https://github.com/blockstack/blockstack-core/graphs/contributors).
diff --git a/_core/faq_technical.md b/_core/faq_technical.md
new file mode 100644
index 00000000..c04e1613
--- /dev/null
+++ b/_core/faq_technical.md
@@ -0,0 +1,185 @@
+---
+layout: core
+permalink: /:collection/:path.html
+---
+# Blockstack Technical FAQ
+{:.no_toc}
+* TOC
+{:toc}
+
+
+
+This document lists frequently-asked questions and answers to technical
+questions about Blockstack.
+
+If you are new to Blockstack, you should read the
+[non-technical FAQ](https://blockstack.org/faq) first.
+
+If you have a technical question that gets frequently asked on the
+[forum](https://forum.blockstack.org) or [Slack](https://blockstack.slack.com),
+feel free to send a pull-request with the question and answer.
+
+## Who should build on Blockstack?
+
+Everyone! But more seriously, if you are building an application in JavaScript
+that requires sign-in and storage you should look at using Blockstack. The APIs
+we provide are not only decentralized (No dependency on Google, Facebook, or
+other OAuth provider) but easier to use than traditional OAuth. Also you no
+longer have to maintain and secure databases with all your user information.
+That data is stored securely with the people who created it.
+
+## What is a "serverless" app?
+
+The application itself should not run application-specific functionality on a server. All of its functionality should run on end-points. However, the application may use non-app-specific servers with the caveat that they must not be part of the trusted computing base. This is the case with storage systems like Amazon S3 and Dropbox, for example, because Blockstack's data is signed and verified end-to-end (so the storage systems are not trusted to serve data). Serverless can also mean applications where some amount of server-side logic is still written by the application developer but unlike traditional architectures is run in stateless compute containers that are event-triggered, ephemeral (may only last for one invocation)
+
+
+## How are Blockstack domains different from normal DNS domains?
+
+Blockstack domains are not registered on the traditional DNS run by an organized called ICANN. Instead they're registered on a blockchain in a fully decentralized way. This means that Blockstack domains are truly owned by their owners and cannot be taken away. All Blockstack domains have public keys by default (public keys are required to own the domains), unlike the traditional DNS where a small fraction of domains get the (optional) public key certificates.
+
+## What is a virtual chain?
+
+Blockstack is designed around a "virtual chain" concept, where nodes only need to reach consensus on the shared "virtual chain" they're interested in. Virtual chains do not interact with one another, and a single blockchain can host many virtual chains. These virtual chains can live in any blockchain for which there exists a driver, and virtual chain clients only need to execute their virtual chain transactions (i.e. Blockstack only processes Blockstack virtual chain transactions).
+
+## What is Blockstack Core and who is working on it?
+
+Blockstack Core is the reference implementation of the Blockstack protocol described in our white paper. It consists of a couple of parts:
+
+- Virtualchain implementation: This is a python library that parses the underlying blockchain (Bitcoin) and builds the state of the Blockstack DNS.
+- Blockstack Core: Uses the Virtualchain to build the DNS state and comes to a consensus on that state in a peer network (Atlas).
+- Blockstack API: Indexes the data stored by Blockstack Core and makes it available in a performant way to applications.
+
+The project is open-source and anyone can contribute! The major contributors are mostly employees of Blockstack PBC. You can see the full list of contributors here: https://github.com/blockstack/blockstack-core/graphs/contributors
+
+
+## How is Blockstack different from Ethereum for building decentralized apps?
+
+You can think of Ethereum as a "heavy" blockchain that does everything for you. All the complexity is handled on-chain, computations are run there, and all scalability and security concerns need to be handled at the blockchain level. It amounts to a "mainframe" that runs all the applications in the ecosystem.
+
+Blockstack puts minimal logic into a blockchain and handles scalability outside of the blockchain by re-using existing internet infrastructure. Our architectural design mirrors how computing has developed; moving from mainframes to smaller networked entities.
+
+Read more about the differences between Blockstack and Ethereum dapps in the following forum post: https://forum.blockstack.org/t/what-is-the-difference-between-blockstack-and-ethereum/781/2
+
+## Can Blockstack only run on Bitcoin?
+
+The model we're currently exploring is where Blockstack can process multiple blockchains to construct the global state where each namespace is tied to a single blockchain. Meaning that say the .id namespace is defined to run on Bitcoin and a .eth namespace is defined to run on Ethereum. Blockstack can process transactions from both blockchains and update the state of namespaces, but the consistency of any given namespace depends only on the underlying blockchain it was defined on.
+
+## Does Blockstack use a DHT (Distributed Hash Table)?
+
+It does not, as of November 2016. It uses a much more reliable system called the Atlas Network. Details here: https://blog.blockstack.org/blockstack-core-v0-14-0-release-aad748f46d#.30gzlthdw
+
+## Can the Blockstack network fork?
+
+Yes, the Blockstack network can fork if the underlying blockchain encounters a deep fork. In this case, blockstack nodes on either side of the fork will diverge from one another.
+
+We have yet to encounter a deep fork. If this does happen, then Blockstack will use the virtualchain state on the majority fork once the fork resolves.
+
+We also hard fork the network once a year to make protocol breaking changes and upgrade the network. The last one of these happened on block `488500` on the bitcoin blockchain. There are more details about the fork in this forum post: https://forum.blockstack.org/t/blockstack-annual-hard-fork-2017/1618
+
+## How is the Blockstack network upgraded over time? What parties need to agree on an upgrade?
+
+We're working on an on-chain voting strategy similar to how mining works, where anyone can cast a vote proportional to the amount of Bitcoin burned. Similar to how Bitcoin upgrades, a new feature will activate if a certain threshold (e.g. 80%) of votes consistently request its adoption over a given time interval (e.g. a couple weeks).
+
+Until then, we will publicly announce the availability of new software, with the promise that each release will bring highly-desired features to make upgrading worth the users' whiles.
+
+## Who gets the registration fees for name registrations?
+
+With the current design, names are purchased by paying tribute with Bitcoin mining fees.
+
+
+## Where are the current core developers based? What are the requirements for being a core developer?
+
+Most of the core developers work in NYC and Hong Kong. Developers who've contributed to the [core open-source software](https://github.com/blockstack/blockstack-core) over a long enough time period, by default, get included in the list of core developers. There is no formal process for being part of this informal list. Core developers, generally, have the ability to write high-quality code, understand distributed systems and applied crypto, and share a vision of building a truly decentralized internet and are dedicated to that cause.
+
+## I heard some companies working on Blockstack have raised venture capital, how does that impact the project?
+
+Blockstack, like Linux, is an open-source project with a GPLv3 license for the core technology. Just like different companies build apps and services on top of Linux and have different individual business models, there are companies who're building apps & services for Blockstack on top of the core open-source technology and these companies have various business models and funding sources respectively. Having more venture-backed companies join the ecosystem for a decentralized internet is a good thing for everyone participating in the ecosystem including users and developers.
+
+## Where is my data stored and how do I control who access it?
+
+You control where your data is stored (you could run your own server, or use your own cloud storage - Dropbox, Amazon S3, and keep backups across all). You then use those places as locations pointed to by the URLs in your Blockstack ID's zone file.
+
+## Why should I trust the information, like name ownership or public key mappings, read from Blockstack?
+
+Blockstack records are extremely hard to tamper with. This is because the bindings for name ownership (names on Blockstack are owned by public keys) are announced in a proof-of-work blockchain (Bitcoin) and to change these binding an attacker will need to come up with a blockchain with more proof-of-work than the current Bitcoin blockchain but with a different history. Bitcoin's [current hash rate](https://blockchain.info/charts/hash-rate) makes this task almost impossible for non-state actors.
+
+## Can anyone register a TLD?
+
+Yes, anyone can register a TLD. If a TLD has not been registered already and you're willing to pay the registration fee for it, you can go ahead and register that TLD. There is no centralized party that can stop you from registering a TLD.
+
+
+## What programming language can I use to build these apps?
+
+To make apps that run in the web browser using Blockstack, you can use JavaScript and any of the same web frameworks or libraries you use today such as React, AngularJs, Vue.js or jQuery. The Blockstack Core is implementated in Python, but you can use any language you like for native apps as long as you are able to consume a JSON REST API.
+
+
+## Do I need to run a full Blockstack node to use Blockstack?
+
+tl;dr: You don't, but its very easy to.
+
+To reduce the overhead involved in getting started we maintain a fleet of Blockstack Core nodes that your Blockstack applications connect to by default. If you want to run your own we provide detailed instructions on our [install page](https://blockstack.org/install). It only takes about 5-10 minutes to spin up your full node!
+
+## What is the capacity per block for registrations using Blockstack?
+
+Initial registrations can be done at an order of hundreds per block and once an identity is registered you can do “unlimited” updates to the data because that is off-chain. We’re also working on a more scalable solution where a very large number of identities can be registered but that’s not live yet and is in the pipeline as a rough benchmark. in summer 2015, Blockstack did 30,000+ identity registrations in a matter of few days live on the blockchain and Blockstack was actually throttling its servers and not taking up more than 100-200 transactions per block. It could’ve easily taken up more transactions without impacting the network.
+
+## What language is the Blockstack software written in?
+
+Python 2 and Node.js
+
+## What incentives are there to run a Blockstack node?
+
+Running a Blockstack node keeps you secure by ensuring that your app gets the right names and public keys. It's not expensive; it takes as much resources as a Chrome tab.
+
+## Can Blockstack apps scale, given that Blockstack uses blockchains which don't scale that well?
+
+Yes. Blockstack only uses the blockchain for name registration. Everything else happens off-chain, so apps work just as fast as they do on the Web.
+
+## What if the current companies and developers working on Blockstack disappear, would the network keep running?
+
+Yes, the Blockstack network will keep running. All of Blockstack's code is open-source and anyone can deploy Blockstack nodes or maintain the code. Further, Blockstack nodes don't need to coordinate with each other to function. Any node that a user deploys can function correctly independently.
+
+
+## Where does Blockstack keep my app data?
+
+As a Blockstack user, you can choose exactly where your data gets stored.
+Blockstack uses a decentralized storage system called
+[Gaia](https://github.com/blockstack/gaia) to host your data. Gaia is different
+from other storage systems because it lets you securely host your data wherever you want---in cloud
+storage providers, on your personal server, or in another decentralized storage
+system like BitTorrent or IPFS.
+
+When you register, you are given a default Gaia hub that replicates your
+data to a bucket in Microsoft Azure. However, you can configure and
+deploy your own Gaia hub and have Blockstack store your data there instead.
+
+The [Blockstack Naming Service]({{ site.baseurl }}/core/naming/introduction.html) and the [Atlas network]({{ site.baseurl }}/core/atlas/overview.html) work together to help other users discover your
+app-specific public data, given your Blockstack ID.
+
+## What is a Blockstack Subdomain?
+
+This is also a Blockstack ID, and can be used for all the things a Blockstack ID
+can be used for. The only difference is that they have the format `foo.bar.baz`
+instead of `bar.baz`. For example,
+[jude.personal.id](https://core.blockstack.org/v1/users/jude.personal.id) is a
+Blockstack ID, and is a subdomain of `personal.id`.
+
+Subdomains are first-class Blockstack IDs---they can be used for all the same
+things that an on-chain Blockstack ID can be used for, and they have all of
+the same safety properties. They are globally unique, they are strongly owned
+by a private key, and they are human-readable.
+
+Subdomains are considerably cheaper than Blockstack IDs, since hundreds of them
+can be registered with a single transaction. The [BNS
+documentation]({{ site.baseurl }}/core/naming/introduction.html) describes them in detail.
+
+Subdomains provide a fast, inexpensive way to onboard many users at once.
+
+## Can I get a Blockstack ID without spending Bitcoin?
+
+Blockstack subdomains can be obtained without spending Bitcoin
+by asking a subdomain registrar to create one for you.
+
+## Is there a Blockstack name explorer?
+
+Yes! It's at https://explorer.blockstack.org
diff --git a/_core/figures/test-screen.png b/_core/figures/test-screen.png
new file mode 100644
index 00000000..c47fc26b
Binary files /dev/null and b/_core/figures/test-screen.png differ
diff --git a/_core/gaia.md b/_core/gaia.md
new file mode 100644
index 00000000..ecdb12ac
--- /dev/null
+++ b/_core/gaia.md
@@ -0,0 +1 @@
+The documentation has been moved to [docs.blockstack.org](https://docs.blockstack.org/), please update your bookmarks.
diff --git a/_core/glossary.md b/_core/glossary.md
new file mode 100644
index 00000000..ecdb12ac
--- /dev/null
+++ b/_core/glossary.md
@@ -0,0 +1 @@
+The documentation has been moved to [docs.blockstack.org](https://docs.blockstack.org/), please update your bookmarks.
diff --git a/_core/install-api.md b/_core/install-api.md
new file mode 100644
index 00000000..8bbb0c2d
--- /dev/null
+++ b/_core/install-api.md
@@ -0,0 +1,88 @@
+---
+layout: core
+permalink: /:collection/:path.html
+---
+# Blockstack API
+{:.no_toc}
+* TOC
+{:toc}
+
+
+Step-by-step instructions for deploying a Blockstack API node on Debian or
+Ubuntu are below.
+
+- **Step 1:** Make sure you have Blockstack Core running locally (see [instructions](https://github.com/blockstack/blockstack-core/blob/master/README.md#quick-start)).
+
+- **Step 2:** Make sure you have [virtualenv installed](http://docs.python-guide.org/en/latest/dev/virtualenvs/).
+Then, setup the API:
+```
+$ sudo apt-get install -y python-pip memcached rng-tools python-dev libmemcached-dev zlib1g-dev libgmp-dev libffi-dev libssl-dev
+$ sudo service memcached start
+$ sudo pip install virtualenv
+$ sudo npm -g install aglio
+$ virtualenv api && source api/bin/activate
+$ git clone https://github.com/blockstack/blockstack-core.git
+$ cd blockstack-core/
+$ pip install .
+$ pip install -r api/requirements.txt
+$ blockstack setup_wallet
+$ blockstack api start
+$ deactivate
+$ ./build_docs.sh public_api
+```
+
+### Search Subsystem
+
+If you want to enable the search subsystem in your installation, you can
+follow the instructions [here](search.html).
+
+### Nginx Deployment
+
+For a production deployment we recommend using nginx and uwsgi:
+
+- **Step 1:** Install nginx and uWSGI:
+```
+$ sudo apt-get install -y nginx
+$ sudo pip install uwsgi
+```
+- **Step 2:** Copy [this sample nginx sites file](../api/nginx/config/nginx_sites-available/blockstack_api) to
+
+> /etc/nginx/sites-available/blockstack_api
+
+and edit the paths depending on the uwsgi blockstack_api socket directory (defaults to /tmp/blockstack_api.sock)
+You can test your nginx settings:
+```
+$ sudo nginx -t
+```
+- **Step 3:** Copy [this sample systemd service file](../api/nginx/config/systemd_system/blockstack_api.service) to
+
+> /etc/systemd/system/blockstack_api.service
+
+and edit the service user and blockstack paths depending on where your blockstack repo is located, and
+where your virtualenv is located.
+
+Note: The following sed commands will work if the virtualenv is currently active and your shell is in the repo's root directory.
+
+```
+$ sudo sed -i "s/User\=USER/User\=$USER/" /etc/systemd/system/blockstack_api.service
+$ sudo sed -i "s#/path/to/blockstack#$PWD#" /etc/systemd/system/blockstack_api.service
+$ sudo sed -i "s#/path/to/virtualenv#$VIRTUAL_ENV#" /etc/systemd/system/blockstack_api.service
+```
+
+- **Step 4:** Get a security certificate from [Let's Encrypt](https://letsencrypt.org/).
+```
+$ git clone https://github.com/certbot/certbot.git
+$ cd certbot/
+$ ./certbot-auto --nginx -d
+```
+
+And copy the cert files to the path given in the nginx sites file earlier.
+
+- **Step 5:** Start nginx and the Blockstack API uwsgi server:
+```
+sudo systemctl restart blockstack_api
+sudo systemctl restart nginx
+```
+
+If you run into any issues, please [submit a Github issue](https://github.com/blockstack/blockstack-core/issues) and we'll update these
+instructions.
diff --git a/_core/interactive_regtest_macros.md b/_core/interactive_regtest_macros.md
new file mode 100644
index 00000000..cc4a5359
--- /dev/null
+++ b/_core/interactive_regtest_macros.md
@@ -0,0 +1,3 @@
+Documentation for setting up the regtest mode for Blockstack Browser
+using core's integration tests in macOS and Linux has
+moved [here](../integration_tests).
diff --git a/_core/memcached.md b/_core/memcached.md
new file mode 100644
index 00000000..44eae4aa
--- /dev/null
+++ b/_core/memcached.md
@@ -0,0 +1,45 @@
+---
+layout: core
+permalink: /:collection/:path.html
+---
+# Installing Memcached
+
+The Blockstack API optionally uses memcached and pylibmc for scaling read-only
+calls. If you want to enable this functionality then you should have memcached
+running locally.
+
+### Memcached on Debian & Ubuntu:
+
+```
+$ sudo apt-get install -y python-dev libmemcached-dev zlib1g-dev
+$ pip install pylibmc
+```
+
+### Memcached on macOS:
+
+Easiest way to install memcached on macOS is by using [Homebrew](https://brew.sh/).
+
+After installing Homebrew:
+
+```
+$ brew install memcached
+$ brew install libmemcached
+$ pip install pylibmc --install-option="--with-libmemcached=/usr/local/Cellar/libmemcached/1.0.18_1/"
+```
+
+After installing, you can start memcached and check if it's running properly:
+
+```
+$ memcached -d
+$ echo stats | nc localhost 11211
+```
+
+### Memcached on Heroku
+
+To deploy on Heroku:
+
+```bash
+$ heroku create
+$ heroku addons:add memcachedcloud
+$ git push heroku master
+```
diff --git a/_core/namespace_creation.md b/_core/namespace_creation.md
new file mode 100644
index 00000000..ecdb12ac
--- /dev/null
+++ b/_core/namespace_creation.md
@@ -0,0 +1 @@
+The documentation has been moved to [docs.blockstack.org](https://docs.blockstack.org/), please update your bookmarks.
diff --git a/_core/naming/architecture.md b/_core/naming/architecture.md
new file mode 100644
index 00000000..b1f8e197
--- /dev/null
+++ b/_core/naming/architecture.md
@@ -0,0 +1,87 @@
+---
+layout: core
+permalink: /:collection/:path.html
+---
+# Understand the Architecture
+
+The BNS node is the heart of the system. It is responsible for building up
+and replicating global name state.
+
+There are three parts to BNS that developers should be aware of. They are:
+
+* **The BNS indexer**. This module crawls the blockchain and builds
+ up its name database. BNS indexers do not contain any private or sensitive
+state, and can be deployed publicly. We maintain a fleet of them at
+`https://node.blockstack.org:6263` for developers to use to get started.
+
+* **The BNS API**. This module gives
+ developers a *stable RESTful API* for interacting with the BNS network.
+We provide one for developers to experiment with at `https://core.blockstack.org`.
+
+* **BNS clients**. These communicate with the BNS API module in order to
+ resolve names. Internally, they generate and send transactions to register
+and modify names.
+
+The BNS indexer and BNS API comprise the **BNS node**. An architectural schematic appears below.
+
+```
+ +-------------------------------------------------------+
+ RESTful | +----------------+ +--------------------+ |
++--------+ API | | | private API | | |
+| client |<------------>| BNS API module |<----------->| BNS indexer module | |
++--------+ | | | | | |
+ | | +----------------+ | +----------------+ | |
+ | | | | name database | | |
+ | | | +----------------+ | |
+ | | +--------------------+ |
+ | | BNS node ^ |
+ | +------------------------------------------|------------+
+ | |
+ | v
+ | blockchain transactions +--------------------+
+ +------------------------------------------------->| blockchain peer |
+ +--------------------+
+
+Figure 1: BNS architecture overview. Clients talk to the BNS API module to
+resolve names, and generate and send blockchain transactions to register and
+modify names. The API module talks to the indexer module and gives clients
+a stable, Web-accessible interface for resolving names. The indexer module reads
+the blochchain via a blockchain peer, over the blockchain's peer network.
+
+Blockstack Core currently implements the API module and indexer module as separate
+daemons (`blockstack api` and `blockstack-core`, respectively). However, this
+is an implementation detail, and may change in the future.
+```
+
+The BNS indexer implements the blockchain consensus rules and network protocols.
+Its main responsibility is to build up and replicate all of the name state. It does
+not have any public APIs of its own.
+
+The BNS API modules allows users and developers to resolve names via a RESTful
+interface. Resolution can be done with vanilla `curl` or `wget`.
+BNS applications should use the BNS API module for name resolution.
+They should not attempt to talk to a BNS indexer directly, because its API is not stable and is not meant
+for consumption by any other process except for the API module.
+
+Registering and managing names require generating and sending blockchain
+transactions, which requires running a BNS client. We provide two reference
+BNS clients:
+
+* The [Blockstack Browser](https://github.com/blockstack/blockstack-browser) gives users
+and developers a graphical UI to resolve, register and manage names. This is the recommended
+way to interact with BNS.
+* The Blockstack CLI gives developers low-level
+control over resolving, registering, and managing names.
+A new CLI that uses [blockstack.js](https://github.com/blockstack/blockstack.js)
+is under development, and will replace the existing CLI program.
+
+We recommend that new developers use the [Blockstack
+Browser](https://github.com/blockstack/blockstack-browser).
+
+Developers who want to make their own client programs that do not use
+the reference client library code should read the
+[BNS transaction wire format]({{ site.baseurl }}/core/wire-format.html) document for generating and
+sending their own transactions.
+
+The examples in this document focus on resolving names using `curl`. We refer
+the reader to client-specific documentation for registering and managing names.
diff --git a/_core/naming/comparison.md b/_core/naming/comparison.md
new file mode 100644
index 00000000..5282d816
--- /dev/null
+++ b/_core/naming/comparison.md
@@ -0,0 +1,119 @@
+---
+layout: core
+permalink: /:collection/:path.html
+---
+# Naming system feature comparison
+{:.no_toc}
+
+BNS is not the only naming system in wide-spread use, nor is it the only
+decentralized naming system that implements human-readable, globally-unique, and
+strongly-owned names. This page describes some other naming systems in
+comparison to Blockstack:
+
+* TOC
+{:toc}
+
+
+## Blockstack vs DNS
+
+Blockstack and DNS both implement naming systems, but in fundamentally
+different ways. Blockstack *can be used* for resolving host names to IP
+addresses, but this is not its default use-case. The [Blockstack Naming
+Service]({{ site.baseurl }}/core/naming/introduction.html) (BNS) instead behaves
+more like a decentralized
+[LDAP](https://en.wikipedia.org/wiki/Lightweight_Directory_Access_Protocol) system for
+resolving user names to user data.
+
+While DNS and BNS handle different problems, they share some terminology and
+serialization formats. However, it is important to recognize that this is the
+*only* thing they have in common---BNS has fundamentally different semantics
+than DNS:
+
+* **Zone files**: Blockstack stores a DNS zone file for each name. However,
+the semantics of a BNS zone file are nothing like the semantics of a DNS zone
+file---the only thing they have in common is their format.
+A "standard" Blockstack zone files only have `URI` and `TXT` resource records
+that point to the user's application data. Moreover, a Blockstack ID has a
+*history* of zone files, and historic zone files can alter the way in which a
+Blockstack ID gets resolved (DNS has no such concept). It is conceivable that an advanced
+user could add `A` and `AAAA` records to their Blockstack ID's zone file,
+but these are not honored by any Blockstack software at this time.
+
+* **Subdomains**: Blockstack has the concept of a subdomain, but it is
+ semantically very different from a DNS subdomain. In Blockstack, a subdomain
+is a Blockstack ID whose state and transaction history are anchored to the
+blockchain, but stored within an on-chain Blockstack ID's zone file history.
+Unlike DNS subdomains, a BNS subdomain has
+its own owner and is a first-class BNS name---all subdomains are resolvable,
+and only the subdomain's owner can update the subdomain's records. The only thing BNS subdomains and DNS
+subdomains have in common is the name format (e.g. `foo.bar.baz` is a subdomain
+of `bar.baz` in both DNS and BNS).
+
+More details can be found in the [Blockstack vs
+DNS]({{ site.baseurl }}/core/naming/comparison.html) document. A feature
+comparison can be found at the end of the [Blockstack Naming
+Service]({{ site.baseurl }}/core/naming/introduction.html) document.
+
+## Blockstack vs Namecoin
+
+Namecoin also implements a decentralized naming service on top of a blockchain,
+just like BNS. In fact, early versions of Blockstack were built on Namecoin.
+However, [it was discovered](https://www.usenix.org/node/196209) that Namecoin's
+merged mining with Bitcoin regularly placed it under the *de facto* control of a single
+miner. This prompted a re-architecting of the system to be *portable* across
+blockchains, so that if Blockstack's underlying blockchain (currently Bitcoin)
+ever became insecure, the system could migrate to a more secure blockchain.
+
+A feature comparison can be found at the end of the [Blockstack Naming
+Service]({{ site.baseurl }}/core/naming/introduction.html) document.
+
+## Blockstack vs ENS
+
+ENS also implements a decentralized naming system on top of a blockchain, but as
+a smart contract on Ethereum. Like BNS, ENS is geared towards resolving names
+to off-chain state (ENS names resolve to a hash, for example). Moreover, ENS is
+geared towards providing programmatic control over names with Turing-complete
+on-chain resolvers.
+
+BNS has a fundamentally different relationship with blockchains than ENS.
+WHereas ENS tries to use on-chain logic as much as possible, BNS
+tries to use the blockchain as little as possible. BNS only uses it to store a
+database log for name operations (which are interpreted with an off-chain BNS
+node like Blockstack Core). BNS name state and BNS subdomains reside entirely
+off-chain in the Atlas network. This has allowed BNS to migrate from blockchain
+to blockchain in order to survive individual blockchain failures, and this has
+allowed BNS developers to upgrade its consensus rules without having to get the
+blockchain's permission (see the [virtualchain
+paper](https://blockstack.org/virtualchain.pdf) for details).
+
+## Summary feature comparison
+
+
+The following feature table provides a quick summary how BNS differs from other naming systems
+
+| Feature | BNS | [ENS](https://ens.domains/) | DNS | [Namecoin](https://namecoin.org/) |
+|----------------------------|-----|-----|-----|----------|
+| Globally unique names | X | X | X | X |
+| Human-readable names | X | X | X | X |
+| Strongly-owned names | X | X | | X |
+| Names are enumerable | X | | | X |
+| Registration times | 1-2 hours | ~1 week | ~1 day | 1-2 hours |
+| Subdomain registration times | 1 hour (instant with [#750](https://github.com/blockstack/blockstack-core/issues/750)) | varies | instant | ~1 hour |
+| Anyone can make a TLD/namespace | X | [1] | | [1] |
+| TLD/Namespace owners get registration fees | X | | X | |
+| TLD/Namespace can be seeded with initial names | X | | X | |
+| Portable across blockchains | X | | N/A | |
+| Off-chain names | X | | N/A | |
+| Off-chain name state | X | X | N/A | |
+| Name provenance | X | X | | X |
+| [DID](http://identity.foundation) support | X | | | |
+| Turing-complete namespace rules | | X | X | |
+| Miners are rewarded for participating | [1] | | N/A | X |
+
+[1] Requires support in higher-level applications. These systems are not aware
+of the existence of namespaces/TLDs at the protocol level.
+
+[2] Blockstack Core destroys the underlying blockchain token to pay for
+registration fees when there is no pay-to-namespace-creator address set in the
+name's namespace. This has the effect of making the blockchain miners' holdings
+slightly more valuable.
diff --git a/_core/naming/creationhowto.md b/_core/naming/creationhowto.md
new file mode 100644
index 00000000..5fe740eb
--- /dev/null
+++ b/_core/naming/creationhowto.md
@@ -0,0 +1,57 @@
+---
+layout: core
+permalink: /:collection/:path.html
+---
+# Creating a Namespace
+
+There are four steps to creating a namespace:
+
+1. **Send a `NAMESPACE_PREORDER` transaction** ([live example](https://www.blocktrail.com/BTC/tx/5f00b8e609821edd6f3369ee4ee86e03ea34b890e242236cdb66ef6c9c6a1b28)).
+This is the first step. This registers the *salted hash* of the namespace with BNS nodes, and burns the
+requisite amount of cryptocurrency. In addition, it proves to the
+BNS nodes that user has honored the BNS consensus rules by including
+a recent *consensus hash* in the transaction
+(see the section on [BNS forks](#bns-forks) for details).
+
+2. **Send a `NAMESPACE_REVEAL` transaction** ([live example](https://www.blocktrail.com/BTC/tx/ab54b1c1dd5332dc86b24ca2f88b8ca0068485edf0c322416d104c5b84133a32)).
+This is the second step. This reveals the salt and the namespace ID (pairing it with its
+`NAMESPACE_PREORDER`), it reveals how long names last in this namespace before
+they expire or must be renewed, and it sets a *price function* for the namespace
+that determines how cheap or expensive names its will be. The price function takes
+a name in this namespace as input, and outputs the amount of cryptocurrency the
+name will cost (i.e. by examining how long the name is, and whether or not it
+has any vowels or non-alphabet characters). The namespace creator
+has the option to collect name registration fees for the first year of the
+namespace's existence by setting a *namespace creator address*.
+
+3. **Seed the namespace with `NAME_IMPORT` transactions** ([live example](https://www.blocktrail.com/BTC/tx/c698ac4b4a61c90b2c93dababde867dea359f971e2efcf415c37c9a4d9c4f312)).
+Once the namespace has been revealed, the user has the option to populate it with a set of
+names. Each imported name is given both an owner and some off-chain state.
+This step is optional---namespace creators are not required to import names.
+
+4. **Send a `NAMESPACE_READY` transaction** ([live example](https://www.blocktrail.com/BTC/tx/2bf9a97e3081886f96c4def36d99a677059fafdbd6bdb6d626c0608a1e286032)).
+This is the final step of the process. It *launches* the namespace, which makes it available to the
+public. Once a namespace is ready, anyone can register a name in it if they
+pay the appropriate amount of cryptocurrency (according to the price funtion
+revealed in step 2).
+
+The reason for the `NAMESPACE_PREORDER/NAMESPACE_REVEAL` pairing is to prevent
+frontrunning. The BNS consensus rules require a `NAMESPACE_REVEAL` to be
+paired with a previous `NAMESPACE_PREORDER` sent within the past 24 hours.
+If it did not do this, then a malicious actor could watch the blockchain network
+and race a victim to claim a namespace.
+
+Namespaces are created on a first-come first-serve basis. If two people try to
+create the same namespace, the one that successfully confirms both the
+`NAMESPACE_PREORDER` and `NAMESPACE_REVEAL` wins. The fee burned in the
+`NAMESPACE_PREORDER` is spent either way.
+
+Once the user issues the `NAMESPACE_PREORDER` and `NAMESPACE_REVEAL`, they have
+1 year before they must send the `NAMESPACE_READY` transaction. If they do not
+do this, then the namespace they created disappears (along with all the names
+they imported).
+
+Developers wanting to create their own namespaces should read the [namespace
+creation]({{ site.baseurl }}/core/naming/namespaces.html) document. It is highly recommended that
+developers individula support to create your own namespace, given the large amount of
+cryptocurrency at stake.
diff --git a/_core/naming/did.md b/_core/naming/did.md
new file mode 100644
index 00000000..e166e3a0
--- /dev/null
+++ b/_core/naming/did.md
@@ -0,0 +1,99 @@
+---
+layout: core
+permalink: /:collection/:path.html
+---
+# Decentralized Identifiers (DIDs)
+
+BNS nodes are compliant with the emerging
+[Decentralized Identity Foundation](http://identity.foundation) protocol
+specification for decentralized identifiers (DIDs).
+
+Each name in BNS has an associated DID. The DID format for BNS is:
+
+```
+ did:stack:v0:{address}-{index}
+```
+
+Where:
+* `{address}` is an on-chain public key hash (e.g. a Bitcoin address).
+* `{index}` refers to the `nth` name this address created.
+
+For example, the DID for `personal.id` is
+`did:stack:v0:1dARRtzHPAFRNE7Yup2Md9w18XEQAtLiV-0`, because the name
+`personal.id` was the first-ever name created by
+`1dARRtzHPAFRNE7Yup2Md9w18XEQAtLiV`.
+
+As another example, the DID for `jude.id` is `did:stack:v0:16EMaNw3pkn3v6f2BgnSSs53zAKH4Q8YJg-1`.
+Here, the address `16EMaNw3pkn3v6f2BgnSSs53zAKH4Q8YJg` had created one earlier
+name in history prior to this one (which happens to be `abcdefgh123456.id`).
+
+The purpose of a DID is to provide an eternal identifier for a public key.
+The public key may change, but the DID will not.
+
+Blockstack Core implements a DID method of its own
+in order to be compatible with other systems that use DIDs for public key resolution.
+In order for a DID to be resolvable, all of the following must be true for a
+name:
+
+* The name must exist
+* The name's zone file hash must be the hash of a well-formed DNS zone file
+* The DNS zone file must be present in the BNS [Atlas Network]({{ site.baseurl }}/core/atlas/overview.html)
+* The DNS zone file must contain a `URI` resource record that points to a signed
+ JSON Web Token
+* The public key that signed the JSON Web Token (and is included with it) must
+ hash to the address that owns the name
+
+Not all names will have DIDs that resolve to public keys. However, names created by the [Blockstack
+Browser](https://github.com/blockstack/blockstack-browser) will have DIDs that
+do.
+
+Developers can programmatically resolve DIDs via the Python API:
+
+```Python
+>>> import blockstack
+>>> blockstack.lib.client.resolve_DID('did:stack:v0:16EMaNw3pkn3v6f2BgnSSs53zAKH4Q8YJg-1', hostport='https://node.blockstack.org:6263')
+{'public_key': '020fadbbcea0ff3b05f03195b41cd991d7a0af8bd38559943aec99cbdaf0b22cc8'}
+```
+
+A RESTful API is under development.
+
+
+# DID Encoding for Subdomains
+
+Every name and subdomain in BNS has a DID. The encoding is slightly different
+for subdomains, so the software can determine which code-path to take.
+
+* For on-chain BNS names, the `{address}` is the same as the Bitcoin address
+ that owns the name. Currently, both version byte 0 and version byte 5
+addresses are supported (i.e. addresses starting with `1` or `3`, meaning `p2pkh` and
+`p2sh` addresses).
+
+* For off-chain BNS subdomains, the `{address}` has version byte 63 for
+ subdomains owned by a single private key, and version byte 50 for subdomains
+owned by a m-of-n set of private keys. That is, subdomain DID addresses start
+with `S` or `M`, respectively.
+
+The `{index}` field for a subdomain's DID is distinct from the `{index}` field
+for a BNS name's DID, even if the same created both names and subdomains.
+For example, the name `abcdefgh123456.id` has the DID `did:stack:v0:16EMaNw3pkn3v6f2BgnSSs53zAKH4Q8YJg-0`,
+because it was the first name created by `16EMaNw3pkn3v6f2BgnSSs53zAKH4Q8YJg`.
+However, `16EMaNw3pkn3v6f2BgnSSs53zAKH4Q8YJg` *also* created `jude.statism.id`
+as its first subdomain name. The DID for `jude.statism.id` is
+`did:stack:v0:SSXMcDiCZ7yFSQSUj7mWzmDcdwYhq97p2i-0`. Note that the address
+`SSXMcDiCZ7yFSQSUj7mWzmDcdwYhq97p2i` encodes the same public key hash as the address
+`16EMaNw3pkn3v6f2BgnSSs53zAKH4Q8YJg` (the only difference between these two
+strings is that the first is base58check-encoded with version byte 0, and the
+second is encoded with version byte 63).
+
+You can see this play out in practice with the following code snippit:
+
+```python
+>>> import blockstack
+>>> blockstack.lib.client.get_name_record('jude.statism.id', hostport='https://node.blockstack.org:6263')['address']
+u'16EMaNw3pkn3v6f2BgnSSs53zAKH4Q8YJg'
+>>> import virtualchain
+>>> virtualchain.address_reencode('16EMaNw3pkn3v6f2BgnSSs53zAKH4Q8YJg', version_byte=63)
+'SSXMcDiCZ7yFSQSUj7mWzmDcdwYhq97p2i'
+>>> blockstack.lib.client.resolve_DID('did:stack:v0:SSXMcDiCZ7yFSQSUj7mWzmDcdwYhq97p2i-0', hostport='https://node.blockstack.org:6263')
+{'public_key': '020fadbbcea0ff3b05f03195b41cd991d7a0af8bd38559943aec99cbdaf0b22cc8'}
+```
diff --git a/_core/naming/forks.md b/_core/naming/forks.md
new file mode 100644
index 00000000..d789b274
--- /dev/null
+++ b/_core/naming/forks.md
@@ -0,0 +1,126 @@
+---
+layout: core
+permalink: /:collection/:path.html
+---
+# BNS Forks
+
+BNS effectively uses a public blockchain to store a database log. A BNS peer
+bootstraps itself by downloading and replaying the database log from the
+blockchain, and in doing so, will calculate the same name database state as
+every other (honest) BNS peer that has the same view of the blockchain.
+
+Crucially, BNS is built on top of a public blockchain that is *unaware* of BNS's existence.
+This means that the blockchain peers do not validate BNS transactions. Instead,
+the BNS peer needs to do so, and must know how to *reject* both invalid transactions
+as well as well-formed transactions from dishonest peers (i.e. peers that do not
+follow the same consensus rules).
+
+BNS nodes do not directly communicate with one another---by design, the set of
+BNS peers is not enumerable. The only shared communication medium between BNS
+peers is the blockchain.
+
+To identify and reject invalid and malicious transactions without the blockchain's help,
+the log of name operations embedded in the blockchain is constructed as a
+[fork\*-consistent](http://www.scs.stanford.edu/~jinyuan/bft2f.pdf) database
+log. Fork\*-consistency is a [consistency
+model](https://en.wikipedia.org/wiki/Consistency_model) whereby the state
+replicas in all of the nodes exhibit the following properties:
+
+* Each correct peer maintains a history of well-formed, valid state operations. In this
+ case, each correct BNS node maintains a copy of the history blockchain transactions
+that encoded well-formed, valid name operations.
+
+* Each honest peer's history contains the sequence of all operations that it
+ sent. That is, a user's BNS peer's transaction log will contain the sequence of all valid
+transactions that the user's client wrote to the blockchain.
+
+* If two peers accept operations *op* and *op'* from the same correct client,
+ then both of their logs will have the both operations in the same order. If
+*op'* was accepted before *op*, then both peers' logs are identical up to *op'*.
+In BNS, this means that if two peers both accept a given transaction, then it
+means that they have accepted the same sequence of prior transactions.
+
+This means that unlike with blockchains,
+there can be *multiple long-lived conflicting forks* of the BNS database log.
+However, due to fork\*-consistency, a correct BNS peer will only process *one*
+of these forks, and will *ignore* transactions from peers in other forks. In other words,
+fork\*-consistency partitions the set of BNS peers into different **fork-sets**,
+where all peers in a fork-set process each other's transactions, but the
+completely ignore peers in other fork-sets.
+
+BNS nodes identify which fork set they belong to using a **consensus hash**. The
+consensus hash is a cryptographic digest of a node's operation
+history. Each BNS peer calculates a new consensus hash each time it processes a
+new block, and stores the history of consensus hashes for each block it
+processed.
+
+Two honest BNS peers can quickly determine if they are in the same fork-set by querying
+each other's consensus hashes for a given block. If they match, then they are
+in the same fork-set (assming no hash collisions).
+
+A BNS client executes a name operation on a specific fork-set by including a
+recent consensus hash from that fork-set in the blockchain transaction.
+At the same time, the BNS consensus rules state that a transaction can only be
+accepted if it included a recent valid consensus hash.
+This means that all BNS nodes in the client's desired fork-set will accept
+the transaction, and all other BNS nodes not in the fork-set will ignore it.
+You can see where the consensus hash is included in blockchain transactions by reading
+the [transaction wire format]({{ site.baseurl }}/core/wire-format.html) document.
+
+## Fork-set Selection
+
+The blockchain linearizes the history of transactions, which means that
+in general, there exists a fork-set for each distinct set of BNS
+consensus rules. For example, the Blockstack Core [2016 hard fork](https://github.com/blockstack/blockstack-core/blob/master/release_notes/changelog-0.14.md)
+and [2017 hard fork](https://github.com/blockstack/blockstack-core/blob/master/release_notes/changelog-0.17.md) both introduced new consensus
+rules, which means at the time of this writing there are three possible fork-sets:
+the pre-2016 fork-set, the 2016-2017 fork-set, and the post-2017 fork-set.
+The [public BNS nodes](https://node.blockstack.org:6263) are always running
+in the fork-set with the latest consensus rules.
+
+BNS clients are incentivized to communicate with peers in the fork-set that has
+the most use, since this fork-set's name database will encode name/state
+bindings that are the most widely-accepted and understood by users.
+To identify this fork-set, a BNS client needs to learn one of
+its recent consensus hashes. Once it has a recent consensus hash, it can
+query an *untrusted* BNS node for a copy of
+its name database, and use the consensus hash to verify that the name database
+was used to generate it.
+
+How does a BNS node determine whether or not a consensus hash corresponds to the
+most widely-used fork-set? There are two strategies:
+
+* Determine whether or not a *characteristic transaction* was accepted by the
+widely-used fork-set. If a client knows that a specific transaction belongs to
+the widely-used fork-set and not others, then they can use the consensus hash to
+efficiently determine whether or not a given node belongs to this fork-set.
+
+* Determine how much "economic activity" exists in a fork-set by inspecting
+the blockchain for burned cryptocurrency tokens. Namespace and name
+registrations are structured in a way that sends cryptocurrency tokens to either
+a well-known burn address, or to an easily-queried pay-to-namespace-creator
+address.
+
+Both strategies rely on the fact that the consensus hash is calculated as a
+[Merkle skip-list](https://github.com/blockstack/blockstack-core/issues/146)
+over the BNS node's accepted transactions. A client can use a consensus hash to
+determine whether or not a transaction *T* was accepted by a node with *O(log
+n)* time and space complexity. We call the protocol for resolving a consensus hash to a specific transaction
+**Simplified Name Verification** (SNV). See our [paper on the subject](https://blockstack.org/virtualchain_dccl16.pdf)
+for details of how SNV works under the hood.
+
+If the client has a consensus hash and knows of a characteristic transaction in the widely-used fork-set,
+it can use SNV to determine whether or not a node belongs to the fork-set that accepted it.
+
+If the client knows about multiple conflicting consensus hashes,
+they can still use SNV to determine which one corresponds
+to the most-used fork-set. To do so, the client would use a
+[blockchain explorer](https://explorer.blockstack.org) to find the
+list of transactions that burned cryptocurrency tokens. Each of these
+transactions will be treated as potential characteristic transactions:
+the client would first select the subset of transactions that are well-formed
+BNS transactions, and then use SNV to determine which of them correspond to which
+consensus hashes. The client chooses the consensus hash that corresponds
+to the fork-set with the highest cumulative burn.
+
+Work is currently underway to automate this process.
diff --git a/_core/naming/introduction.md b/_core/naming/introduction.md
new file mode 100644
index 00000000..96af2a62
--- /dev/null
+++ b/_core/naming/introduction.md
@@ -0,0 +1,145 @@
+---
+layout: core
+permalink: /:collection/:path.html
+---
+# Blockstack Naming Service (BNS)
+{:.no_toc}
+
+This document gives an overview of how the Blockstack Naming Service work. This
+section introduces you to BNS and explains the following concepts:
+
+* TOC
+{:toc}
+
+The ([Blockstack Core](https://github.com/blockstack/blockstack-core))
+repository is the reference implementation of the Blockstack Naming Service.
+
+
+## What is BNS
+
+The Blockstack Naming Service (BNS) is a network system that binds names
+to off-chain state without relying on any central points of control.
+It does so by embedding a log of its control-plane messages within a public blockchain, like Bitcoin.
+
+Each BNS peer determines the state of each name by indexing these specially-crafted
+transactions. In doing so, each peer independently calculates the same global
+name state.
+
+Names in BNS have three properties:
+
+* **Names are globally unique.** The protocol does not allow name collisions, and all
+ well-behaved nodes resolve a given name to the same state.
+* **Names are human-meaningful.** Each name is chosen by its creator.
+* **Names are strongly-owned.** Only the name's owner can change the state it
+ resolves to. Specifically, a name is owned by one or more ECDSA private keys.
+
+Internally, a BNS node implements a replicated name database. Each BNS node keeps itself
+synchronized to all of the other ones in the world, so queries on one BNS node
+will be the same on other nodes. BNS nodes allow a name's owner to bind
+up to 40Kb of off-chain state to their name, which will be replicated to all
+BNS nodes via the [Atlas network]({{ site.baseurl }}/core/atlas/overview.html).
+
+BNS nodes extract the name database log from an underlying blockchain (Blockstack
+Core currently uses Bitcoin, and had used Namecoin in the past).
+BNS uses the blockchain to establish a shared "ground truth" for the system: as long as
+two nodes have the same view of the blockchain, then they will build up the same
+database.
+
+The biggest consequence for developers is that in BNS, reading name state is
+fast and cheap but writing name state is slow and expensive. This is because
+registering and modifying names requires one or more transactions to be sent to
+the underlying blockchain, and BNS nodes will not process them until they are
+sufficiently confirmed. Users and developers need to acquire and spend
+the requisite cryptocurrency (i.e. Bitcoin) to send BNS transactions.
+
+## Motivation behind naming services
+
+We rely on naming systems in everyday life, and they play a critical
+role in many different applications. For example, when you look up a
+friend on social media, you are using the platform's naming service to resolve
+their name to their profile. When you look up a website, you are using the
+Domain Name Service to
+resolve the hostname to its host's IP address. When you check out a Git branch, you
+are using your Git client to resolve the branch name to a commit hash.
+When you look up someone's PGP key on a keyserver, you are resolving
+their key ID to their public key.
+
+What kinds of things do we want to be true about names? In BNS, names are
+globally unique, names are human-meaningful, and names are strongly-owned.
+However, if you look at these examples, you'll see that each of them only
+guarantees *two* of these properties. This limits how useful they can be.
+
+* In DNS and social media, names are globally unique and human-readable, but not
+strongly-owned. The system operator has the
+final say as to what each names resolves to.
+ * **Problem**: Clients must trust the system to make the right
+ choice in what a given name resolves to. This includes trusting that
+ no one but the system administrators can make these changes.
+
+* In Git, branch names are human-meaningful
+and strongly-owned, but not globally unique. Two different Git nodes may resolve the same
+branch name to different unrelated repository states.
+ * **Problem**: Since names can refer to conflicting state, developers
+ have to figure out some other mechanism to resolve ambiguities. In Git's
+ case, the user has to manually intervene.
+
+* In PGP, names are key IDs. They are
+are globally unique and cryptographically owned, but not human-readable. PGP
+key IDs are derived from the keys they reference.
+ * **Problem**: These names are difficult for most users to
+ remember since they do not carry semantic information relating to their use in the system.
+
+BNS names have all three properties, and none of these problems. This makes it a
+powerful tool for building all kinds of network applications. With BNS, we
+can do the following and more:
+
+* Build domain name services where hostnames can't be hijacked.
+* Build social media platforms where user names can't be stolen by phishers.
+* Build version control systems where repository branches do not conflict.
+* Build public-key infrastructure where it's easy for users to discover and
+ remember each other's keys.
+
+
+# Organization of BNS
+
+BNS names are organized into a global name hierarchy. There are three different
+layers in this hierarchy related to naming:
+
+* **Namespaces**. These are the top-level names in the hierarchy. An analogy
+ to BNS namespaces are DNS top-level domains. Existing BNS namespaces include
+`.id`, `.podcast`, and `.helloworld`. All other names belong to exactly one
+namespace. Anyone can create a namespace, but in order for the namespace
+to be persisted, it must be *launched* so that anyone can register names in it.
+Namespaces are not owned by their creators.
+
+* **BNS names**. These are names whose records are stored directly on the
+ blockchain. The ownership and state of these names are controlled by sending
+blockchain transactions. Example names include `verified.podcast` and
+`muneeb.id`. Anyone can create a BNS name, as long as the namespace that
+contains it exists already. The state for BNS names is usually stored in the [Atlas
+network]({{ site.baseurl }}/core/atlas/overview.html).
+
+* **BNS subdomains**. These are names whose records are stored off-chain,
+but are collectively anchored to the blockchain. The ownership and state for
+these names lives within the [Atlas network]({{ site.baseurl }}/core/atlas/overview.html). While BNS
+subdomains are owned by separate private keys, a BNS name owner must
+broadcast their subdomain state. Example subdomains include `jude.personal.id`
+and `podsaveamerica.verified.podcast`. Unlike BNS namespaces and names, the
+state of BNS subdomains is *not* part of the blockchain consensus rules.
+
+A feature comparison matrix summarizing the similarities and differences
+between these name objects is presented below:
+
+| Feature | **Namespaces** | **BNS names** | **BNS Subdomains** |
+|---------|----------------|---------------|--------------------|
+| Globally unique | X | X | X |
+| Human-meaningful | X | X | X |
+| Owned by a private key | | X | X |
+| Anyone can create | X | X | [1] |
+| Owner can update | | X | [1] |
+| State hosted on-chain | X | X | |
+| State hosted off-chain | | X | X |
+| Behavior controlled by consensus rules | X | X | |
+| May have an expiration date | | X | |
+
+[1] Requires the cooperation of a BNS name owner to broadcast its transactions
diff --git a/_core/naming/manage.md b/_core/naming/manage.md
new file mode 100644
index 00000000..ad4d7493
--- /dev/null
+++ b/_core/naming/manage.md
@@ -0,0 +1,101 @@
+---
+layout: core
+permalink: /:collection/:path.html
+---
+# Manage BNS Names
+{:.no_toc}
+
+This section teaches you how to manage your namespace, it contains the
+following sections:
+
+* TOC
+{:toc}
+
+## Overview of management
+
+Once you register a BNS name, you have the power to change its zone file hash,
+change its public key hash, destroy it (i.e. render it unresolvable),
+or renew it. The BNS consensus rules ensure that *only* you, as the owner of
+the name's private key, have the ability to carry out these operations.
+
+Each of these operations are executed by sending a specially-formatted
+blockchain transaction to the blockchain, which BNS nodes read and process.
+The operations are listed below:
+
+| Transaction Type | Description |
+|------------------|-------------|
+| `NAME_UPDATE` | This changes the name's zone file hash. Any 20-byte string is allowed. |
+| `NAME_TRANSFER` | This changes the name's public key hash. In addition, the current owner has the option to atomically clear the name's zone file hash (so the new owner won't "receive" the zone file). |
+| `NAME_REVOKE` | This renders a name unresolvable. You should do this if your private key is compromised. |
+| `NAME_RENEWAL` | This pushes back the name's expiration date (if it has one), and optionally both sets a new zone file hash and a new public key hash. |
+
+The reference BNS clients---
+[blockstack.js](https://github.com/blockstack/blockstack.js) and the [Blockstack
+Browser](https://github.com/blockstack/blockstack-browser)---can handle creating
+and sending all of these transactions for you.
+
+## NAME_UPDATE ([live example](https://www.blocktrail.com/BTC/tx/e2029990fa75e9fc642f149dad196ac6b64b9c4a6db254f23a580b7508fc34d7))
+
+A `NAME_UPDATE` transaction changes the name's zone file hash. You would send
+one of these transactions if you wanted to change the name's zone file contents.
+For example, you would do this if you want to deploy your own [Gaia
+hub](https://github.com/blockstack/gaia) and want other people to read from it.
+
+A `NAME_UPDATE` transaction is generated from the name, a recent [consensus
+hash](#bns-forks), and the new zone file hash. The reference clients gather
+this information automatically. See the [transaction format]({{ site.baseurl }}/core/wire-format.html)
+document for details on how to construct this transaction.
+
+## NAME_TRANSFER ([live example](https://www.blocktrail.com/BTC/tx/7a0a3bb7d39b89c3638abc369c85b5c028d0a55d7804ba1953ff19b0125f3c24))
+
+A `NAME_TRANSFER` transaction changes the name's public key hash. You would
+send one of these transactions if you wanted to:
+
+* Change your private key
+* Send the name to someone else
+
+When transferring a name, you have the option to also clear the name's zone
+file hash (i.e. set it to `null`).
+This is useful for when you send the name to someone else, so the
+recipient's name does not resolve to your zone file.
+
+The `NAME_TRANSFER` transaction is generated from the name, a recent [consensus
+hash](#bns-forks), and the new public key hash. The reference clients gather
+this information automatically. See the [transaction format]({{ site.baseurl }}/core/wire-format.html)
+document for details on how to construct this transaction.
+
+## NAME_REVOKE ([live example](https://www.blocktrail.com/BTC/tx/eb2e84a45cf411e528185a98cd5fb45ed349843a83d39fd4dff2de47adad8c8f))
+
+A `NAME_REVOKE` transaction makes a name unresolvable. The BNS consensus rules
+stipulate that once a name is revoked, no one can change its public key hash or
+its zone file hash. The name's zone file hash is set to `null` to prevent it
+from resolving.
+
+You should only do this if your private key is compromised, or if you want to
+render your name unusable for whatever reason. It is rarely used in practice.
+
+The `NAME_REVOKE` operation is generated using only the name. See the
+[transaction format]({{ site.baseurl }}/core/wire-format.html) document for details on how to construct
+it.
+
+## NAME_RENEWAL ([live example](https://www.blocktrail.com/BTC/tx/e543211b18e5d29fd3de7c0242cb017115f6a22ad5c6d51cf39e2b87447b7e65))
+
+Depending in the namespace rules, a name can expire. For example, names in the
+`.id` namespace expire after 2 years. You need to send a `NAME_RENEWAL` every
+so often to keep your name.
+
+A `NAME_RENEWAL` costs both transaction fees and registration fees. You will
+pay the registration cost of your name to the namespace's designated burn address when you
+renew it. You can find this fee using the `/v1/prices/names/{name}` endpoint.
+
+When a name expires, it enters a month-long "grace period" (5000 blocks). It
+will stop resolving in the grace period, and all of the above operations will
+cease to be honored by the BNS consensus rules. You may, however, send a
+`NAME_RENEWAL` during this grace period to preserve your name.
+
+If your name is in a namespace where names do not expire, then you never need to
+use this transaction.
+
+When you send a `NAME_RENEWAL`, you have the option of also setting a new public
+key hash and a new zone file hash. See the [transaction format]({{ site.baseurl }}/core/wire-format.html)
+document for details on how to construct this transaction.
diff --git a/_core/naming/namespaces.md b/_core/naming/namespaces.md
new file mode 100644
index 00000000..3d01fe23
--- /dev/null
+++ b/_core/naming/namespaces.md
@@ -0,0 +1,78 @@
+---
+layout: core
+permalink: /:collection/:path.html
+---
+# Understand Namespaces
+
+Namespaces are the top-level naming objects in BNS.
+
+They control a few properties about the names within them:
+* How expensive they are to register
+* How long they last before they have to be renewed
+* Who (if anyone) receives the name registration fees
+* Who is allowed to seed the namespace with its initial names.
+
+At the time of this writing, by far the largest BNS namespace is the `.id`
+namespace. Names in the `.id` namespace are meant for resolving user
+identities. Short names in `.id` are more expensive than long names, and have
+to be renewed by their owners every two years. Name registration fees are not
+paid to anyone in particular---they are instead sent to a "black hole" where
+they are rendered unspendable (the intention is to discourage ID sqautters).
+
+Unlike DNS, *anyone* can create a namespace and set its properties. Namespaces
+are created on a first-come first-serve basis, and once created, they last
+forever.
+
+However, creating a namespace is not free. The namespace creator must *burn*
+cryptocurrency to do so. The shorter the namespace, the more cryptocurrency
+must be burned (i.e. short namespaces are more valuable than long namespaces).
+For example, it cost Blockstack PBC 40 BTC to create the `.id` namespace in 2015
+(in transaction
+`5f00b8e609821edd6f3369ee4ee86e03ea34b890e242236cdb66ef6c9c6a1b281`).
+
+Namespaces can be between 1 and 19 characters long, and are composed of the
+characters `a-z`, `0-9`, `-`, and `_`.
+
+## Namespace Organization
+
+BNS names are organized into a global name hierarchy. There are three different
+layers in this hierarchy related to naming:
+
+* **Namespaces**. These are the top-level names in the hierarchy. An analogy
+ to BNS namespaces are DNS top-level domains. Existing BNS namespaces include
+`.id`, `.podcast`, and `.helloworld`. All other names belong to exactly one
+namespace. Anyone can create a namespace, but in order for the namespace
+to be persisted, it must be *launched* so that anyone can register names in it.
+Namespaces are not owned by their creators.
+
+* **BNS names**. These are names whose records are stored directly on the
+ blockchain. The ownership and state of these names are controlled by sending
+blockchain transactions. Example names include `verified.podcast` and
+`muneeb.id`. Anyone can create a BNS name, as long as the namespace that
+contains it exists already. The state for BNS names is usually stored in the [Atlas
+network]({{ site.baseurl }}/core/atlas/overview.html).
+
+* **BNS subdomains**. These are names whose records are stored off-chain,
+but are collectively anchored to the blockchain. The ownership and state for
+these names lives within the [Atlas network]({{ site.baseurl }}/core/atlas/overview.html). While BNS
+subdomains are owned by separate private keys, a BNS name owner must
+broadcast their subdomain state. Example subdomains include `jude.personal.id`
+and `podsaveamerica.verified.podcast`. Unlike BNS namespaces and names, the
+state of BNS subdomains is *not* part of the blockchain consensus rules.
+
+A feature comparison matrix summarizing the similarities and differences
+between these name objects is presented below:
+
+| Feature | **Namespaces** | **BNS names** | **BNS Subdomains** |
+|---------|----------------|---------------|--------------------|
+| Globally unique | X | X | X |
+| Human-meaningful | X | X | X |
+| Owned by a private key | | X | X |
+| Anyone can create | X | X | [1] |
+| Owner can update | | X | [1] |
+| State hosted on-chain | X | X | |
+| State hosted off-chain | | X | X |
+| Behavior controlled by consensus rules | X | X | |
+| May have an expiration date | | X | |
+
+[1] Requires the cooperation of a BNS name owner to broadcast its transactions
diff --git a/_core/naming/pickname.md b/_core/naming/pickname.md
new file mode 100644
index 00000000..f19113e7
--- /dev/null
+++ b/_core/naming/pickname.md
@@ -0,0 +1,159 @@
+---
+layout: core
+permalink: /:collection/:path.html
+---
+# Choose a name
+{:.no_toc}
+
+This section explains how to choose and create a namespace, it contains the
+following sections:
+
+* TOC
+{:toc}
+
+
+## Intended uses for a namespace
+
+The intention is that each application can create its own BNS
+namespace for its own purposes. Applications can use namespaces for things like:
+
+* Giving users a SSO system, where each user registers their public key under a
+ username. Blockstack applications do this with names in the `.id` namespace,
+for example.
+
+* Providing a subscription service, where each name is a 3rd party that provides
+a service for users to subscribe to. For example, names in
+`.podcast` point to podcasts that users of the DotPodcast app can subscribe to.
+* Implementing software licenses, where each name corresponds to an access key.
+ Unlike conventional access keys, access keys implemented as names
+can be sold and traded independently. The licensing fee (paid as a name
+registration) would be set by the developer and sent to a developer-controlled
+blockchain address.
+
+Names within a namespace can serve any purpose the developer wants. The ability
+to collect registration fees for 1 year after creating the namespace not only
+gives developers the incentive to get users to participate in the app, but also
+gives them a way to measure economic activity.
+
+Developers can query individual namespaces and look up names within them using
+the BNS API.
+
+## List all namespaces in existence (reference).
+
+```bash
+$ curl https://core.blockstack.org/v1/namespaces
+[
+ "id",
+ "helloworld",
+ "podcast"
+]
+```
+
+## List all names within a namespace (reference).
+
+```bash
+$ curl https://core.blockstack.org/v1/namespaces/id/names?page=0
+[
+ "0.id",
+ "0000.id",
+ "000000.id",
+ "000001.id",
+ "00000111111.id",
+ "000002.id",
+ "000007.id",
+ "0011sro.id",
+ "007_007.id",
+ "00n3w5.id",
+ "00r4zr.id",
+ "00w1k1.id",
+ "0101010.id",
+ "01jack.id",
+ "06nenglish.id",
+ "08.id",
+ "0cool_f.id",
+ "0dadj1an.id",
+ "0nelove.id",
+ "0nename.id"
+...
+]
+```
+
+Each page returns a batch of 100 names.
+
+## Get the Cost to Register a Namespace (reference).
+
+```bash
+$ curl https://core.blockstack.org/v1/prices/namespaces/test
+{
+ "satoshis": 40000000
+}
+```
+
+If you want to register a namespace, please see the [namespace creation section]({{ site.baseurl }}/core/naming/namespaces.html).
+
+## Getting the Current Consensus Hash (reference).
+
+```bash
+$ curl -sL https://core.blockstack.org/v1/blockchains/bitcoin/consensus
+{
+ "consensus_hash": "98adf31989bd937576aa190cc9f5fa3a"
+}
+```
+
+A recent consensus hash is required to create a `NAMESPACE_PREORDER` transaction. The reference
+BNS clients do this automatically. See the [transaction format]({{ site.baseurl }}/core/wire-format.html)
+document for details on how the consensus hash is used to construct the
+transaction.
+
+## Create a namespace
+
+ There are four steps to creating a namespace:
+
+1. **Send a `NAMESPACE_PREORDER` transaction** (live example).
+This is the first step. This registers the *salted hash* of the namespace with BNS nodes, and burns the
+requisite amount of cryptocurrency. In addition, it proves to the
+BNS nodes that user has honored the BNS consensus rules by including
+a recent *consensus hash* in the transaction
+(see the section on [BNS forks](#bns-forks) for details).
+
+2. **Send a `NAMESPACE_REVEAL` transaction** (live example).
+This is the second step. This reveals the salt and the namespace ID (pairing it with its
+`NAMESPACE_PREORDER`), it reveals how long names last in this namespace before
+they expire or must be renewed, and it sets a *price function* for the namespace
+that determines how cheap or expensive names its will be. The price function takes
+a name in this namespace as input, and outputs the amount of cryptocurrency the
+name will cost (i.e. by examining how long the name is, and whether or not it
+has any vowels or non-alphabet characters). The namespace creator
+has the option to collect name registration fees for the first year of the
+namespace's existence by setting a *namespace creator address*.
+
+3. **Seed the namespace with `NAME_IMPORT` transactions** (live example).
+Once the namespace has been revealed, the user has the option to populate it with a set of
+names. Each imported name is given both an owner and some off-chain state.
+This step is optional---namespace creators are not required to import names.
+
+4. **Send a `NAMESPACE_READY` transaction** (live example).
+This is the final step of the process. It *launches* the namespace, which makes it available to the
+public. Once a namespace is ready, anyone can register a name in it if they
+pay the appropriate amount of cryptocurrency (according to the price funtion
+revealed in step 2).
+
+The reason for the `NAMESPACE_PREORDER/NAMESPACE_REVEAL` pairing is to prevent
+frontrunning. The BNS consensus rules require a `NAMESPACE_REVEAL` to be
+paired with a previous `NAMESPACE_PREORDER` sent within the past 24 hours.
+If it did not do this, then a malicious actor could watch the blockchain network
+and race a victim to claim a namespace.
+
+Namespaces are created on a first-come first-serve basis. If two people try to
+create the same namespace, the one that successfully confirms both the
+`NAMESPACE_PREORDER` and `NAMESPACE_REVEAL` wins. The fee burned in the
+`NAMESPACE_PREORDER` is spent either way.
+
+Once the user issues the `NAMESPACE_PREORDER` and `NAMESPACE_REVEAL`, they have
+1 year before they must send the `NAMESPACE_READY` transaction. If they do not
+do this, then the namespace they created disappears (along with all the names
+they imported).
+
+Developers wanting to create their own namespaces should read the [namespace creation section]({{ site.baseurl }}/core/naming/namespaces.html) document. It is highly recommended that
+developers request individual support before creating their own space, given the large amount of
+cryptocurrency at stake.
diff --git a/_core/naming/register.md b/_core/naming/register.md
new file mode 100644
index 00000000..12858de4
--- /dev/null
+++ b/_core/naming/register.md
@@ -0,0 +1,110 @@
+---
+layout: core
+permalink: /:collection/:path.html
+---
+# Register a name
+{:.no_toc}
+
+This section explains registering BNS names and provides instructions for methods
+you can use to understandt the cost of namespace registration.
+
+* TOC
+{:toc}
+
+## Understand registration
+
+Registering a BNS name costs cryptocurrency. This cost comes from two sources:
+
+* **Transaction fees:** These are the fees imposed by the cost of storing the
+ transaction data to the blockchain itself. They are independent of BNS, since
+all of the blockchain's users are competing to have their transactions included
+in the next block. The blockchain's miners receive the transaction fee.
+
+* **Registration fees:** Each BNS namespace imposes an *additional* fee on how
+ much a name costs. The registration fee is sent to the namespace creator
+during the first year that a namespace exists, and is sent to a burn address
+afterwards. The registration fee is different for each name and is
+determined by the namespace itself, but can be queried in advance by the user.
+
+Registering a name takes two transactions. They are:
+
+* **`NAME_PREORDER` transaction**: This is the first transaction to be sent.
+ It tells all BNS nodes the *salted hash* of the BNS name, and it pays the
+registration fee to the namespace owner's designated address (or the burn
+address). In addition, it proves to the BNS nodes that the client knows about
+the current state of the system by including a recent *consensus hash*
+in the transaction (see the section on [BNS forks](#bns-forks) for details).
+
+* **`NAME_REGISTRATION` transaction**: This is the second transaction to be
+ sent. It reveals the salt and the name to all BNS nodes, and assigns the name
+an initial public key hash and zone file hash
+
+The reason this process takes two transactions is to prevent front-running.
+The BNS consensus rules stipulate that a name can only be registered if its
+matching preorder transaction was sent in the last 24 hours. Because a name
+must be preordered before it is registered, someone watching the blockchain's
+peer network cannot race a victim to claim the name they were trying to
+register (i.e. the attacker would have needed to send a `NAME_PREORDER`
+transaction first, and would have had to have sent it no more than 24 hours
+ago).
+
+Registering a name on top of the Bitcoin blockchain takes 1-2 hours. This is
+because you need to wait for the `NAME_PREORDER` transaction to be sufficiently
+confirmed before sending the `NAME_REGISTRATION` transaction. The BNS nodes
+only register the name once both transactions have at least 6 confirmations
+(which itself usually takes about an hour).
+
+Names are registered on a first-come first-serve basis.
+If two different people try to register the same name at the same time, the
+person who completes the two-step process *earliest* will receive the name. The
+other person's `NAME_REGISTRATION` transaction will be ignored, since it will
+not be considered valid at this point. The registration fee paid by the
+`NAME_PREORDER` will be lost. However, this situation is rare in practice---
+as of early 2018, we only know of one confirmed instance in the system's 3+ years
+of operation.
+
+Fully-qualified names can be between 3 and 37 characters long, and consist of
+the characters `a-z`, `0-9`, `+`, `-`, `_`, and `.`. This is to prevent
+[homograph attacks](https://en.wikipedia.org/wiki/IDN_homograph_attack).
+`NAME_REGISTRATION` transactions that do not conform to this requirement will be
+ignored.
+
+## Getting a Name's Registration Fee ([reference](https://core.blockstack.org/#price-checks-get-name-price))
+
+```bash
+$ curl -sL https://core.blockstack.org/v1/prices/names/helloworld.id | jq -r ".name_price"
+{
+ "btc": 2.5e-05,
+ "satoshis": 2500
+}
+```
+
+Note the use of `jq -r` to select the `"name_price"` field. This API
+endpoint may return other ancilliary data regarding transaction fee estimation,
+but this is the only field guaranteed by this specification to be present.
+
+## Getting the Current Consensus Hash ([reference](https://core.blockstack.org/#blockchain-operations-get-consensus-hash))
+
+```bash
+$ curl -sL https://core.blockstack.org/v1/blockchains/bitcoin/consensus
+{
+ "consensus_hash": "98adf31989bd937576aa190cc9f5fa3a"
+}
+```
+
+The consensus hash must be included in the `NAME_PREORDER` transaction. The BNS
+clients do this automatically. See the [transaction format
+document]({{ site.baseurl }}/core/wire-format.html) for details as to how to include this in the
+transaction.
+
+## Registering a Name
+
+Registration happens through a BNS client, such as the [Blockstack
+Browser](https://github.com/blockstack/blockstack-browser) or
+[blockstack.js](https://github.com/blockstack/blockstack.js).
+The reference BNS clients manage a local Bitcoin wallet, calculate transaction fees
+dynamically and automatically, and broadcast both the `NAME_PREORDER` and
+`NAME_REGISTRATION` transactions at the right times.
+
+If you want to make your own registration client, you should see the
+[transaction format]({{ site.baseurl }}/core/wire-format.html) document.
diff --git a/_core/naming/resolving.md b/_core/naming/resolving.md
new file mode 100644
index 00000000..7f624887
--- /dev/null
+++ b/_core/naming/resolving.md
@@ -0,0 +1,254 @@
+---
+layout: core
+permalink: /:collection/:path.html
+---
+## Resolve a name
+{:.no_toc}
+
+This section explains resolving BNS names and provides instructions for methods
+you can use to accomplish namespace resolution.
+
+* TOC
+{:toc}
+
+## Understand resolution
+
+BNS names are bound to both public keys and to about 40Kb of off-chain state.
+The off-chain state is encoded as a [DNS zone file](https://en.wikipedia.org/wiki/Zone_file),
+which contains routing information for discovering the user's Blockstack data
+(such as their profile and app data, which are hosted in the [Gaia storage
+system](https://github.com/blockstack/gaia)).
+
+The blockchain is not used to store this information directly. Instead, the
+blockchain stores the *public key hash* and the *zone file hash*. When
+indexing the blockchain, each BNS node builds a database with
+three columns: all the on-chain BNS names that have been registered, each
+name's public key hash, and each name's zone file's hash.
+In addition, each BNS node maintains the *transaction history* of each name.
+A developer can resolve a name to any configuration it was in at any prior
+point in time.
+
+Below is an example name table pulled from a live BNS node:
+
+| Name | Public key hash | Zone File Hash |
+|------|-----------------|--------------|
+| `ryan.id` | `15BcxePn59Y6mYD2fRLCLCaaHScefqW2No` | `a455954b3e38685e487efa41480beeb315f4ec65` |
+| `muneeb.id` | `1J3PUxY5uDShUnHRrMyU6yKtoHEUPhKULs` | `37aecf837c6ae9bdc9dbd98a268f263dacd00361` |
+| `jude.id` | `16EMaNw3pkn3v6f2BgnSSs53zAKH4Q8YJg` | `b6e99200125e70d634b17fe61ce55b09881bfafd` |
+| `verified.podcast` | `1MwPD6dH4fE3gQ9mCov81L1DEQWT7E85qH` | `6701ce856620d4f2f57cd23b166089759ef6eabd` |
+| `cicero.res_publica.id` | `1EtE77Aa5AA8etzF2irk56vvkS4v7rZ7PE` | `7e4ac75f9d79ba9d5d284fac19617497433b832d` |
+| `podsaveamerica.verified.podcast` | `1MwPD6dH4fE3gQ9mCov81L1DEQWT7E85qH` | `0d6f090db8945aa0e60759f9c866b17645893a95` |
+
+In practice, the zone file hash is the `RIPEMD160` hash of the `SHA256` hash of
+the zone file, and the public key is the `base58check`-encoded `RIPEMD160` hash
+of the double-`SHA256` hash of the ECDSA public key (i.e. a Bitcoin address).
+
+The BNS consensus rules ensure that
+a BNS name can only be registered if it is not already taken, and that only the
+user who owns the name's private key can change its public key hash or zone file
+hash. This means that a name's public key and zone file can be stored anywhere,
+since they can be authenticated using the hashes discovered by indexing the
+blockchain under the BNS consensus rules.
+
+BNS nodes implement a decentralized storage system for zone files called the
+[Atlas network]({{ site.baseurl }}/core/atlas/overview.html). In this system, BNS nodes eagerly replicate
+all the zone files they know about to one another, so that eventually every BNS
+node has a full replica of all zone files.
+
+The public keys for names are stored off-chain in [Gaia](https://github.com/blockstack/gaia).
+The user controls where their public keys are hosted using the zone file
+contents (if they are hosted online anywhere at all).
+
+Developers can query this table via the BNS API. The API offers routes
+to do the following:
+
+## Look up a name's public key and zone file ([reference](https://core.blockstack.org/#name-querying-get-name-info))
+
+```bash
+$ curl https://core.blockstack.org/v1/names/muneeb.id
+{
+ "address": "1J3PUxY5uDShUnHRrMyU6yKtoHEUPhKULs",
+ "blockchain": "bitcoin",
+ "expire_block": 599266,
+ "last_txid": "7e16e8688ca0413a398bbaf16ad4b10d3c9439555fc140f58e5ab4e50793c476",
+ "status": "registered",
+ "zonefile": "$ORIGIN muneeb.id\n$TTL 3600\n_http._tcp URI 10 1 \"https://gaia.blockstack.org/hub/1J3PUxY5uDShUnHRrMyU6yKtoHEUPhKULs/0/profile.json\"\n",
+ "zonefile_hash": "37aecf837c6ae9bdc9dbd98a268f263dacd00361"
+}
+```
+
+Note that the `zonefile` field is given with the off-chain data that hashes
+to the `zonefile_hash` field.
+
+## List all names the node knows about ([reference](https://core.blockstack.org/#name-querying-get-all-names))
+
+```bash
+$ curl https://core.blockstack.org/v1/names?page=0
+[
+ "judecn.id",
+ "3.id",
+ "4.id",
+ "8.id",
+ "e.id",
+ "h.id",
+ "5.id",
+ "9.id",
+ "i.id",
+ "l.id",
+ "p.id",
+ "w.id",
+ "ba.id",
+ "df.id",
+...
+]
+```
+
+Each page returns 100 names. While no specific ordering is mandated by the
+protocol, the reference implementation orders names by their order of creation
+in the blockchain.
+
+## Look up the history of states a name was in ([reference](https://core.blockstack.org/#name-querying-name-history))
+
+```bash
+$ curl https://core.blockstack.org/v1/names/patrickstanley.id/history
+{
+ "445838": [
+ {
+ "address": "1occgbip7tFDXX9MvzQhcnTUUjcVX2dYK",
+ "block_number": 445838,
+ "burn_address": "1111111111111111111114oLvT2",
+ "consensus_hash": "7b696b6f4060b792d41912068944d73b",
+ "op": "?",
+ "op_fee": 25000,
+ "opcode": "NAME_PREORDER",
+ "preorder_hash": "26bf7874706ac761afdd403ed6b3b9578fb01a34",
+ "sender": "76a91408d0dd44c1f0a3a4f0957ae95901929d7d66d55788ac",
+ "sender_pubkey": "039a8948d339ecbff44cf426cb85d90fce876f1658d385cdc47f007f279be626ea",
+ "txid": "6730ae09574d5935ffabe3dd63a9341ea54fafae62fde36c27738e9ee9c4e889",
+ "vtxindex": 40
+ }
+ ],
+ "445851": [
+ {
+ "address": "17CbHgTgBG3kLedXNneEKBkCTgW2fyrnUD",
+ "block_number": 445838,
+ "consensus_hash": null,
+ "first_registered": 445851,
+ "importer": null,
+ "importer_address": null,
+ "last_creation_op": "?",
+ "last_renewed": 445851,
+ "name": "patrickstanley.id",
+ "name_hash128": "683a3e1ee5f0296833c56e481cf41b77",
+ "namespace_block_number": 373601,
+ "namespace_id": "id",
+ "op": ":",
+ "op_fee": 25000,
+ "opcode": "NAME_REGISTRATION",
+ "preorder_block_number": 445838,
+ "preorder_hash": "26bf7874706ac761afdd403ed6b3b9578fb01a34",
+ "revoked": false,
+ "sender": "76a9144401f3be5311585ea519c1cb471a8dc7b02fd6ee88ac",
+ "sender_pubkey": "039a8948d339ecbff44cf426cb85d90fce876f1658d385cdc47f007f279be626ea",
+ "transfer_send_block_id": null,
+ "txid": "55b8b42fc3e3d23cbc0f07d38edae6a451dfc512b770fd7903725f9e465b2925",
+ "value_hash": null,
+ "vtxindex": 54
+ }
+ ],
+ "445873": [
+ {
+ "address": "17CbHgTgBG3kLedXNneEKBkCTgW2fyrnUD",
+ "block_number": 445838,
+ "consensus_hash": "18b8d69f0182b89ccb1aa536f83be18a",
+ "first_registered": 445851,
+ "importer": null,
+ "importer_address": null,
+ "last_creation_op": "?",
+ "last_renewed": 445851,
+ "name": "patrickstanley.id",
+ "name_hash128": "683a3e1ee5f0296833c56e481cf41b77",
+ "namespace_block_number": 373601,
+ "namespace_id": "id",
+ "op": "+",
+ "op_fee": 25000,
+ "opcode": "NAME_UPDATE",
+ "preorder_block_number": 445838,
+ "preorder_hash": "26bf7874706ac761afdd403ed6b3b9578fb01a34",
+ "revoked": false,
+ "sender": "76a9144401f3be5311585ea519c1cb471a8dc7b02fd6ee88ac",
+ "sender_pubkey": "039a8948d339ecbff44cf426cb85d90fce876f1658d385cdc47f007f279be626ea",
+ "transfer_send_block_id": null,
+ "txid": "dc478659fc684a1a6e1e09901971e82de11f4dfe2b32a656700bf9a3b6030719",
+ "value_hash": "02af0ef21161ad06b0923106f40b994b9e4c1614",
+ "vtxindex": 95
+ }
+ ],
+ "445884": [
+ {
+ "address": "1GZqrVbamkaE6YNveJFWK6cDrCy6bXyS6b",
+ "block_number": 445838,
+ "consensus_hash": "18b8d69f0182b89ccb1aa536f83be18a",
+ "first_registered": 445851,
+ "importer": null,
+ "importer_address": null,
+ "last_creation_op": "?",
+ "last_renewed": 445851,
+ "name": "patrickstanley.id",
+ "name_hash128": "683a3e1ee5f0296833c56e481cf41b77",
+ "namespace_block_number": 373601,
+ "namespace_id": "id",
+ "op": ">>",
+ "op_fee": 25000,
+ "opcode": "NAME_TRANSFER",
+ "preorder_block_number": 445838,
+ "preorder_hash": "26bf7874706ac761afdd403ed6b3b9578fb01a34",
+ "revoked": false,
+ "sender": "76a914aabffa6dd90d731d3a349f009323bb312483c15088ac",
+ "sender_pubkey": null,
+ "transfer_send_block_id": 445875,
+ "txid": "7a0a3bb7d39b89c3638abc369c85b5c028d0a55d7804ba1953ff19b0125f3c24",
+ "value_hash": "02af0ef21161ad06b0923106f40b994b9e4c1614",
+ "vtxindex": 16
+ }
+ ]
+}
+```
+
+All of the above information is extracted from the blockchain. Each top-level
+field encodes the states the name transitioned to at the given block height (e.g.
+445838, 445851, 445873, adn 445884). At each block height, the name's zone file
+hashes are returned in the order they were discovered in the blockchain.
+
+Each name state contains a lot of ancillary data that is used internally by
+other API calls and client libraries. The relevant fields for this document's
+scope are:
+
+* `address`: This is the base58check-encoded public key hash.
+* `name`: This is the name queried.
+* `value_hash`: This is the zone file hash.
+* `opcode`: This is the type of transaction that was processed.
+* `txid`: This is the transaction ID in the underlying blockchain.
+
+The name's *entire* history is returned. This includes the history of the name
+under its previous owner, if the name expired and was reregistered.
+
+## Look up the list of names owned by a given public key hash ([reference](https://core.blockstack.org/#name-querying-get-names-owned-by-address))
+
+```bash
+$ curl https://core.blockstack.org/v1/addresses/bitcoin/16EMaNw3pkn3v6f2BgnSSs53zAKH4Q8YJg
+{
+ "names": [
+ "judecn.id",
+ "patrickstanley1.id",
+ "abcdefgh123456.id",
+ "duckduckgo_tor.id",
+ "jude.id",
+ "blockstacknewyear2017.id",
+ "jude.statism.id"
+ ]
+}
+```
+
+Note that this API endpoint includes names and
+[subdomains](#bns-subdomains).
diff --git a/_core/naming/search.md b/_core/naming/search.md
new file mode 100644
index 00000000..a7bce1f2
--- /dev/null
+++ b/_core/naming/search.md
@@ -0,0 +1,187 @@
+---
+layout: core
+permalink: /:collection/:path.html
+---
+# How to build a Profile Search Index
+
+The search subsystem for Blockstack Core creates an index for data associated
+with registered names in namespaces and makes that data searchable.
+
+The search subsystem is currently meant to index the .id namespace but can
+be easily expanded to include other namespaces.
+
+Currently there are two types of indexes to handle search queries:
+
+* Substring search on usernames, full names, twitter_handle (powered by MongoDB)
+* Raw Lucene index which handles searching extended data e.g., bio.
+
+Search will currently return upto a max of 20 results (can be less depending on the query)
+with data that follows structure of [blockstack IDs](https://github.com/blockstack/blockstack):
+
+In early 2017, the search subsystem was ported over to the new API system, where support for search is provided by the endpoint:
+
+```
+http://localhost:5000/search?query=
+```
+
+This document describes how to setup the search subsystem to respond at that endpoint.
+
+# Installation
+
+- **Step 1:** First, make sure you have [virtualenv installed](http://docs.python-guide.org/en/latest/dev/virtualenvs/).
+Then, setup the API and search subsystem:
+```
+$ sudo apt-get install -y mongodb memcached python-dev libmemcached-dev zlib1g-dev nginx
+$ sudo pip install uwsgi
+$ git clone https://github.com/blockstack/blockstack-core.git --branch api
+$ cd blockstack-core/
+$ sudo pip install .
+$ sudo pip install -r api/requirements.txt
+$ sudo mkdir /var/blockstack-search && sudo chown $USER:$USER /var/blockstack-search
+```
+
+- **Step 2:** Make sure you have Blockstack Core running locally (see [instructions](https://github.com/blockstack/blockstack-core/blob/master/README.md#quick-start)). We highly
+recommend using a local node because the search subsystem issues thousands of calls to
+Blockstack Core for re-indexing and remote nodes can slow down performance.
+
+- **Step 3:** Fetch the data for the .id namespace and respective profiles. Note, you may want to redirect stderr to a file, as there is a lot of debug output.
+
+```
+$ cd api/
+
+$ python -m search.fetch_data --fetch_namespace
+
+$ python -m search.fetch_data --fetch_profiles
+```
+
+- **Step 4:** Create the search index:
+
+```
+python -m search.basic_index --refresh
+```
+
+- **Step 5:** Enable search API endpoint:
+
+```
+$ sed -i 's/SEARCH_API_ENDPOINT_ENABLED \= False/SEARCH_API_ENDPOINT_ENABLED \= True/' config.py
+```
+
+# Usage
+
+You can quickly test the search index from the command line:
+
+```
+python -m search.substring_search --search_name "Fred Wil"
+python -m search.substring_search --search_twitter fredwil
+```
+
+You can also use the search API end-point:
+
+> curl -G {machine_ip}:port/search/name -d "query=muneeb"
+
+Sample Response:
+
+```
+{
+ "people": [
+ {
+ "profile": {
+ "website": [
+ {
+ "url": "http://muneebali.com",
+ "@type": "WebSite"
+ }
+ ],
+ "name": "Muneeb Ali",
+ "address": {
+ "addressLocality": "New York, NY",
+ "@type": "PostalAddress"
+ },
+ "image": [
+ {
+ "contentUrl": "https://s3.amazonaws.com/dx3/muneeb",
+ "@type": "ImageObject",
+ "name": "cover"
+ },
+ {
+ "contentUrl": "https://s3.amazonaws.com/kd4/muneeb",
+ "@type": "ImageObject",
+ "name": "avatar"
+ }
+ ],
+ "@type": "Person",
+ "description": "Co-founder of Blockstack. Interested in distributed systems and blockchains. Previously, PhD at Princeton."
+ },
+ "username": "muneeb"
+ },
+ {
+ "profile": {
+ "message": "This blockchain ID is reserved for Muneeb Ali. If this is you, please email support@onename.com to claim it for free.",
+ "status": "reserved"
+ },
+ "username": "muneebali"
+ },
+ {
+ "profile": {
+ "cover": {
+ "url": "https://s3.amazonaws.com/97p/HHE.jpg"
+ },
+ "v": "0.2"
+ },
+ "username": "muneebali1"
+ }
+
+ ]
+}
+```
+
+## Enabling Elastic Search
+
+### Requirements:
+
+```
+sudo apt-get install mongodb
+sudo apt-get install memcached libmemcached-dev
+sudo apt-get install python2.7-dev
+pip install -r requirements.txt
+```
+
+### Elastic Search
+
+Elastic Search library is not in github and resides at unix/lib/elastic
+
+the current version we're using is *0.90.2*. Download from:
+
+> wget https://download.elasticsearch.org/elasticsearch/elasticsearch/elasticsearch-0.90.2.zip
+
+before installing pylimbmc make sure [memcached]({{ site.baseurl }}/core/memcached.html) is installed.
+
+Ensure that mongodb and elastic search are running
+starting elastic search:
+
+```
+$elasticsearch (on mac)
+bin/elasticsearch -d (on linux)
+```
+
+To test if elastic search is running:
+
+> curl -X GET http://localhost:9200/
+
+returns:
+
+```
+{
+ "ok" : true,
+ "status" : 200,
+ "name" : "Angler",
+ "version" : {
+ "number" : "0.90.2",
+ "snapshot_build" : false,
+ "lucene_version" : "4.3.1"
+ },
+```
+
+Create Index:
+
+> python create_search_index.py --create_index
diff --git a/_core/naming/subdomains.md b/_core/naming/subdomains.md
new file mode 100644
index 00000000..0e01f0f5
--- /dev/null
+++ b/_core/naming/subdomains.md
@@ -0,0 +1,249 @@
+---
+layout: core
+permalink: /:collection/:path.html
+---
+# BNS Subdomains
+
+{:.no_toc}
+
+This section explains BNS subdomains and provides instructions for methods
+you can use to work with them. The following topics are included:
+
+* TOC
+{:toc}
+
+# Overview of subdomains
+
+BNS names are strongly-owned because the owner of its private key can generate
+valid transactions that update its zone file hash and owner. However, this comes at the
+cost of requiring a name owner to pay for the underlying transaction in the
+blockchain. Moreover, this approach limits the rate of BNS name registrations
+and operations to the underlying blockchain's transaction bandwidth.
+
+BNS overcomes this with subdomains. A **BNS subdomain** is a type of BNS name whose state
+and owner are stored outside of the blockchain, but whose existence and
+operation history are anchored to the
+blockchain. In the example table in the [Resolving BNS
+Names](#resolving-bns-names) section, the names `cicero.res_publica.id` and
+`podsaveamerica.verified.podcast` are subdomains.
+
+Like their on-chain counterparts, subdomains are globally
+unique, strongly-owned, and human-readable. BNS gives them their own name state
+and public keys.
+
+Unlike on-chain names, subdomains can be created and managed
+cheaply, because they are broadcast to the
+BNS network in batches. A single blockchain transaction can send up to 120
+subdomain operations.
+
+This is achieved by storing subdomain records in the [Atlas Network]({{ site.baseurl }}/core/atlas/overview.html).
+An on-chain name owner broadcasts subdomain operations by encoding them as
+`TXT` records within a DNS zone file. To broadcast the zone file,
+the name owner sets the new zone file hash with a `NAME_UPDATE` transaction and
+replicates the zone file via Atlas. This, in turn, replicates all subdomain
+operations it contains, and anchors the set of subdomain operations to
+an on-chain transaction. The BNS node's consensus rules ensure that only
+valid subdomain operations from *valid* `NAME_UPDATE` transactions will ever be
+stored.
+
+For example, the name `verified.podcast` once wrote the zone file hash `247121450ca0e9af45e85a82e61cd525cd7ba023`,
+which is the hash of the following zone file:
+
+```bash
+$ curl -sL https://core.blockstack.org/v1/names/verified.podcast/zonefile/247121450ca0e9af45e85a82e61cd525cd7ba023 | jq -r '.zonefile'
+$ORIGIN verified.podcast
+$TTL 3600
+1yeardaily TXT "owner=1MwPD6dH4fE3gQ9mCov81L1DEQWT7E85qH" "seqn=0" "parts=1" "zf0=JE9SSUdJTiAxeWVhcmRhaWx5CiRUVEwgMzYwMApfaHR0cC5fdGNwIFVSSSAxMCAxICJodHRwczovL3BoLmRvdHBvZGNhc3QuY28vMXllYXJkYWlseS9oZWFkLmpzb24iCg=="
+2dopequeens TXT "owner=1MwPD6dH4fE3gQ9mCov81L1DEQWT7E85qH" "seqn=0" "parts=1" "zf0=JE9SSUdJTiAyZG9wZXF1ZWVucwokVFRMIDM2MDAKX2h0dHAuX3RjcCBVUkkgMTAgMSAiaHR0cHM6Ly9waC5kb3Rwb2RjYXN0LmNvLzJkb3BlcXVlZW5zL2hlYWQuanNvbiIK"
+10happier TXT "owner=1MwPD6dH4fE3gQ9mCov81L1DEQWT7E85qH" "seqn=0" "parts=1" "zf0=JE9SSUdJTiAxMGhhcHBpZXIKJFRUTCAzNjAwCl9odHRwLl90Y3AgVVJJIDEwIDEgImh0dHBzOi8vcGguZG90cG9kY2FzdC5jby8xMGhhcHBpZXIvaGVhZC5qc29uIgo="
+31thoughts TXT "owner=1MwPD6dH4fE3gQ9mCov81L1DEQWT7E85qH" "seqn=0" "parts=1" "zf0=JE9SSUdJTiAzMXRob3VnaHRzCiRUVEwgMzYwMApfaHR0cC5fdGNwIFVSSSAxMCAxICJodHRwczovL3BoLmRvdHBvZGNhc3QuY28vMzF0aG91Z2h0cy9oZWFkLmpzb24iCg=="
+359 TXT "owner=1MwPD6dH4fE3gQ9mCov81L1DEQWT7E85qH" "seqn=0" "parts=1" "zf0=JE9SSUdJTiAzNTkKJFRUTCAzNjAwCl9odHRwLl90Y3AgVVJJIDEwIDEgImh0dHBzOi8vcGguZG90cG9kY2FzdC5jby8zNTkvaGVhZC5qc29uIgo="
+30for30 TXT "owner=1MwPD6dH4fE3gQ9mCov81L1DEQWT7E85qH" "seqn=0" "parts=1" "zf0=JE9SSUdJTiAzMGZvcjMwCiRUVEwgMzYwMApfaHR0cC5fdGNwIFVSSSAxMCAxICJodHRwczovL3BoLmRvdHBvZGNhc3QuY28vMzBmb3IzMC9oZWFkLmpzb24iCg=="
+onea TXT "owner=1MwPD6dH4fE3gQ9mCov81L1DEQWT7E85qH" "seqn=0" "parts=1" "zf0=JE9SSUdJTiBvbmVhCiRUVEwgMzYwMApfaHR0cC5fdGNwIFVSSSAxMCAxICJodHRwczovL3BoLmRvdHBvZGNhc3QuY28vb25lYS9oZWFkLmpzb24iCg=="
+10minuteteacher TXT "owner=1MwPD6dH4fE3gQ9mCov81L1DEQWT7E85qH" "seqn=0" "parts=1" "zf0=JE9SSUdJTiAxMG1pbnV0ZXRlYWNoZXIKJFRUTCAzNjAwCl9odHRwLl90Y3AgVVJJIDEwIDEgImh0dHBzOi8vcGguZG90cG9kY2FzdC5jby8xMG1pbnV0ZXRlYWNoZXIvaGVhZC5qc29uIgo="
+36questionsthepodcastmusical TXT "owner=1MwPD6dH4fE3gQ9mCov81L1DEQWT7E85qH" "seqn=0" "parts=1" "zf0=JE9SSUdJTiAzNnF1ZXN0aW9uc3RoZXBvZGNhc3RtdXNpY2FsCiRUVEwgMzYwMApfaHR0cC5fdGNwIFVSSSAxMCAxICJodHRwczovL3BoLmRvdHBvZGNhc3QuY28vMzZxdWVzdGlvbnN0aGVwb2RjYXN0bXVzaWNhbC9oZWFkLmpzb24iCg=="
+_http._tcp URI 10 1 "https://dotpodcast.co/"
+```
+
+Each `TXT` record in this zone file encodes a subdomain-creation.
+For example, `1yeardaily.verified.podcast` resolves to:
+
+```bash
+$ curl https://core.blockstack.org/v1/names/1yeardaily.verified.podcast
+{
+ "address": "1MwPD6dH4fE3gQ9mCov81L1DEQWT7E85qH",
+ "blockchain": "bitcoin",
+ "last_txid": "d87a22ebab3455b7399bfef8a41791935f94bc97aee55967edd5a87f22cce339",
+ "status": "registered_subdomain",
+ "zonefile_hash": "e7acc97fd42c48ed94fd4d41f674eddbee5557e3",
+ "zonefile_txt": "$ORIGIN 1yeardaily\n$TTL 3600\n_http._tcp URI 10 1 \"https://ph.dotpodcast.co/1yeardaily/head.json\"\n"
+}
+```
+
+This information was extracted from the `1yeardaily` `TXT` resource record in the zone
+file for `verified.podcast`.
+
+## Subdomain Lifecycle
+
+Note that `1yeardaily.verified.podcast` has a different public key
+hash (address) than `verified.podcast`. A BNS node will only process a
+subsequent subdomain operation on `1yeardaily.verified.podcast` if it includes a
+signature from this address's private key. `verified.podcast` cannot generate
+updates; only the owner of `1yeardaily.verified.podcast can do so`.
+
+The lifecycle of a subdomain and its operations is shown in Figure 2.
+
+```
+ subdomain subdomain subdomain
+ creation update transfer
++----------------+ +----------------+ +----------------+
+| cicero | | cicero | | cicero |
+| owner="1Et..." | signed | owner="1Et..." | signed | owner="1cJ..." |
+| zf0="7e4..." |<--------| zf0="111..." |<--------| zf0="111..." |<---- ...
+| seqn=0 | | seqn=1 | | seqn=2 |
+| | | sig="xxxx" | | sig="xxxx" |
++----------------+ +----------------+ +----------------+
+ | | |
+ | off-chain | |
+~ ~ ~ ~ | ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~|~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ | ~ ~ ~ ~ ~ ~ ~ ...
+ | on-chain | |
+ V V (zone file hash ) V
++----------------+ +----------------+ +----------------+
+| res_publica.id | | jude.id | | res_publica.id |
+| NAME_UPDATE |<--------| NAME_UPDATE |<--------| NAME_UPDATE |<---- ...
++----------------+ +----------------+ +----------------+
+ blockchain blockchain blockchain
+ block block block
+
+
+Figure 2: Subdomain lifetime with respect to on-chain name operations. A new
+subdomain operation will only be accepted if it has a later "sequence=" number,
+and a valid signature in "sig=" over the transaction body. The "sig=" field
+includes both the public key and signature, and the public key must hash to
+the previous subdomain operation's "addr=" field.
+
+Thesubdomain-creation and subdomain-transfer transactions for
+"cicero.res_publica.id" are broadcast by the owner of "res_publica.id".
+However, any on-chain name ("jude.id" in this case) can broadcast a subdomain
+update for "cicero.res_publica.id".
+```
+
+Subdomain operations are ordered by sequence number, starting at 0. Each new
+subdomain operation must include:
+
+* The next sequence number
+* The public key that hashes to the previous subdomain transaction's address
+* A signature from the corresponding private key over the entire subdomain
+ operation.
+
+If two correctly-signed but conflicting subdomain operations are discovered
+(i.e. they have the same sequence number), the one that occurs earlier in the
+blockchain's history is accepted. Invalid subdomain operations are ignored.
+
+Combined, this ensures that a BNS node with all of the zone files with a given
+subdomain's operations will be able to determine the valid sequence of
+state-transitions it has undergone, and determine the current zone file and public
+key hash for the subdomain.
+
+## Resolving Subdomains
+
+Developers interact with subdomains the same way they interact with names.
+Using the BNS API, a developer can:
+
+### Look up a subdomain's public key and zone file ([reference](https://core.blockstack.org/#name-querying-get-name-info))
+
+```bash
+$ curl https://core.blockstack.org/v1/names/aaron.personal.id
+{
+ "address": "1PwztPFd1s2STMv4Ntq6UPBdYgHSBr5pdF",
+ "blockchain": "bitcoin",
+ "last_txid": "85e8273b0a38d3e9f0af7b4b72faf0907de9f4616afc101caac13e7bbc832394",
+ "status": "registered_subdomain",
+ "zonefile_hash": "a6dda6b74ffecf85f4a162627d8df59577243813",
+ "zonefile_txt": "$ORIGIN aaron.personal.id\n$TTL 3600\n_https._tcp URI 10 1 \"https://gaia.blockstack.org/hub/1PwztPFd1s2STMv4Ntq6UPBdYgHSBr5pdF/profile.json\"\n"
+}
+```
+
+### Look up a subdomain's transaction history ([reference](https://core.blockstack.org/#name-querying-name-history))
+
+```bash
+$ curl https://core.blockstack.org/v1/names/aaron.personal.id/history
+{
+ "509981": [
+ {
+ "address": "1PwztPFd1s2STMv4Ntq6UPBdYgHSBr5pdF",
+ "block_number": 509981,
+ "domain": "personal.id",
+ "name": "aaron.personal.id",
+ "sequence": 0,
+ "txid": "85e8273b0a38d3e9f0af7b4b72faf0907de9f4616afc101caac13e7bbc832394",
+ "value_hash": "a6dda6b74ffecf85f4a162627d8df59577243813",
+ "zonefile": "JE9SSUdJTiBhYXJvbi5wZXJzb25hbC5pZAokVFRMIDM2MDAKX2h0dHBzLl90Y3AgVVJJIDEwIDEgImh0dHBzOi8vZ2FpYS5ibG9ja3N0YWNrLm9yZy9odWIvMVB3enRQRmQxczJTVE12NE50cTZVUEJkWWdIU0JyNXBkRi9wcm9maWxlLmpzb24iCg=="
+ }
+ ]
+}
+```
+
+### Look up the list of names and subdomains owned by a given public key hash ([reference](https://core.blockstack.org/#name-querying-get-names-owned-by-address))
+
+```bash
+$ curl https://core.blockstack.org/v1/addresses/bitcoin/1PwztPFd1s2STMv4Ntq6UPBdYgHSBr5pdF
+{
+ "names": [
+ "aaron.personal.id"
+ ]
+}
+```
+
+## Subdomain Creation and Management
+
+Unlike an on-chain name, a subdomain owner needs an on-chain name owner's help
+to broadcast their subdomain operations. In particular:
+* A subdomain-creation transaction can only be processed by the owner of the on-chain
+name that shares its suffix. For example, only the owner of `res_publica.id`
+can broadcast subdomain-creation transactions for subdomain names ending in
+`.res_publica.id`.
+* A subdomain-transfer transaction can only be broadcast by the owner of the
+on-chain name that created it. For example, the owner of
+`cicero.res_publica.id` needs the owner of `res_publica.id` to broadcast a
+subdomain-transfer transaction to change `cicero.res_publica.id`'s public key.
+* In order to send a subdomain-creation or subdomain-transfer, all
+ of an on-chain name owner's zone files must be present in the Atlas network.
+ This lets the BNS node prove the *absence* of any conflicting subdomain-creation and
+subdomain-transfer operations when processing new zone files.
+* A subdomain update transaction can be broadcast by *any* on-chain name owner,
+ but the subdomain owner needs to find one who will cooperate. For example,
+the owner of `verified.podcast` can broadcast a subdomain-update transaction
+created by the owner of `cicero.res_publica.id`.
+
+That said, to create a subdomain, the subdomain owner generates a
+subdomain-creation operation for their desired name
+and gives it to the on-chain name owner.
+The on-chain name owner then uses Atlas to
+broadcast it to all other BNS nodes.
+
+Once created, a subdomain owner can use any on-chain name owner to broadcast a
+subdomain-update operation. To do so, they generate and sign the requisite
+subdomain operation and give it to an on-chain name owner, who then packages it
+with other subdomain operations into a DNS zone file
+and sends them all out on the Atlas network.
+
+If the subdomain owner wants to change the address of their subdomain, they need
+to sign a subdomain-transfer operation and give it to the on-chain name owner
+who created the subdomain. They then package it into a zone file and broadcast
+it.
+
+## Subdomain Registrars
+
+Because subdomain names are cheap, developers may be inclined to run
+subdomain registrars on behalf of their applications. For example,
+the name `personal.id` is used to register Blockstack application users without
+requiring them to spend any Bitcoin.
+
+We supply a reference
+implementation of a [BNS Subdomain Registrar](https://github.com/blockstack/subdomain-registrar)
+to help developers broadcast subdomain operations. Users would still own their
+subdomain names; the registrar simply gives developers a convenient way for them
+to register and manage them in the context of a particular application.
+Please see the [tutorial on running a subdomain registrar]({{ site.baseurl }}/core/naming/tutorial_subdomains.html) for
+details on how to use it.
diff --git a/_core/naming/tutorial_subdomains.md b/_core/naming/tutorial_subdomains.md
new file mode 100644
index 00000000..d6c5ada3
--- /dev/null
+++ b/_core/naming/tutorial_subdomains.md
@@ -0,0 +1,314 @@
+---
+layout: core
+permalink: /:collection/:path.html
+---
+# Subdomain Design and Implementation
+
+{:.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:
+
+* TOC
+{:toc}
+
+
+## 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/`,
+`/v1/names/`, and `/v1/addresses/bitcoin/`)
+The endpoints which *are* subdomain aware are marked as such in
+[api-specs.md].
+
+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/`,
+`/v1/names/`, and `/v1/addresses/bitcoin/` 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](https://github.com/blockstack/blockstack-core/blob/master/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)
+```
diff --git a/_core/openbazaar.md b/_core/openbazaar.md
new file mode 100644
index 00000000..ecdb12ac
--- /dev/null
+++ b/_core/openbazaar.md
@@ -0,0 +1 @@
+The documentation has been moved to [docs.blockstack.org](https://docs.blockstack.org/), please update your bookmarks.
diff --git a/_core/resolver.md b/_core/resolver.md
new file mode 100644
index 00000000..ecdb12ac
--- /dev/null
+++ b/_core/resolver.md
@@ -0,0 +1 @@
+The documentation has been moved to [docs.blockstack.org](https://docs.blockstack.org/), please update your bookmarks.
diff --git a/_core/search.md b/_core/search.md
new file mode 100644
index 00000000..ecdb12ac
--- /dev/null
+++ b/_core/search.md
@@ -0,0 +1 @@
+The documentation has been moved to [docs.blockstack.org](https://docs.blockstack.org/), please update your bookmarks.
diff --git a/_core/setup_core_portal.md b/_core/setup_core_portal.md
new file mode 100644
index 00000000..98b0d83a
--- /dev/null
+++ b/_core/setup_core_portal.md
@@ -0,0 +1,67 @@
+# About
+
+This document is for **Linux users who do not want to use Docker** to run the
+Blockstack Browser. Instructions are tailored for Ubuntu, but are similar on other distributions.
+
+# Setting up Blockstack Browser Node Application
+
+Install NodeJS through NodeSource PPA
+
+```
+curl -sL https://deb.nodesource.com/setup_7.x | sudo -E bash -
+sudo apt install -y nodejs
+```
+
+Download Blockstack Browser and install its dependencies
+
+```
+git clone https://github.com/blockstack/blockstack-browser.git
+cd blockstack-browser
+npm install node-sass
+npm install
+```
+
+Note that `blockstack-browser` depends on `node-sass` which can sometimes install strangely on Linux, running `npm install node-sass` before trying to install the other dependencies solves that problem.
+
+# Running Blockstack Browser
+
+Start the CORS proxy.
+
+```
+npm run dev-proxy &
+```
+
+Start the Node Application
+
+```
+npm run dev
+```
+
+Then you can open `http://localhost:3000/` in your browser to get to the Blockstack Browser.
+
+
+## Setting up a protocol handler
+
+If you'd like your browser to automatically handle links with the `blockstack:` protocol specifier, you will need to register a protocol handler with your desktop environment. In Ubuntu/Gnome, this can be done by creating a file
+
+`~/.local/share/applications/blockstack.desktop`
+
+With the following contents:
+
+```
+[Desktop Entry]
+Type=Application
+Terminal=false
+Exec=bash -c 'xdg-open http://localhost:3000/auth?authRequest=$(echo "%u" | sed s,blockstack:////*,,)'
+Name=Blockstack-Browser
+MimeType=x-scheme-handler/blockstack;
+```
+
+Then you need to make this file executable, and register it as a protocol handler.
+
+```
+$ chmod +x ~/.local/share/applications/blockstack.desktop
+$ xdg-mime default blockstack.desktop x-scheme-handler/blockstack
+```
+
+Now, `blockstack:` protocol URLs should get handled by your Blockstack Browser. If you're running Browser in your browser's private mode, you may have to copy and paste the link, as this protocol handler will try to open in a regular browser window.
diff --git a/_core/subdomains.md b/_core/subdomains.md
new file mode 100644
index 00000000..ecdb12ac
--- /dev/null
+++ b/_core/subdomains.md
@@ -0,0 +1 @@
+The documentation has been moved to [docs.blockstack.org](https://docs.blockstack.org/), please update your bookmarks.
diff --git a/_core/wire-format.md b/_core/wire-format.md
new file mode 100644
index 00000000..4e84079b
--- /dev/null
+++ b/_core/wire-format.md
@@ -0,0 +1,499 @@
+---
+layout: core
+permalink: /:collection/:path.html
+---
+# Bitcoin wire format
+{:.no_toc}
+
+This page is for organizations who want to be able to create and send name operation transactions to the blockchain(s) Blockstack supports.
+It describes the transaction formats for the Bitcoin blockchain.
+
+* TOC
+{:toc}
+
+## Transaction format
+
+Each Bitcoin transaction for Blockstack contains signatures from two sets of keys: the name owner, and the payer. The owner `scriptSig` and `scriptPubKey` fields are generated from the key(s) that own the given name. The payer `scriptSig` and `scriptPubKey` fields are used to *subsidize* the operation. The owner keys do not pay for any operations; the owner keys only control the minimum amount of BTC required to make the transaction standard. The payer keys only pay for the transaction's fees, and (when required) they pay the name fee.
+
+This construction is meant to allow the payer to be wholly separate from the owner. The principal that owns the name can fund their own transactions, or they can create a signed transaction that carries out the desired operation and request some other principal (e.g. a parent organization) to actually pay for and broadcast the transaction.
+
+The general transaction layout is as follows:
+
+| **Inputs** | **Outputs** |
+| ------------------------ | ----------------------- |
+| Owner scriptSig (1) | `OP_RETURN ` (2) |
+| Payment scriptSig | Owner scriptPubKey (3) |
+| Payment scriptSig... (4) |
+| ... (4) | ... (5) |
+
+(1) The owner `scriptSig` is *always* the first input.
+(2) The `OP_RETURN` script that describes the name operation is *always* the first output.
+(3) The owner `scriptPubKey` is *always* the second output.
+(4) The payer can use as many payment inputs as (s)he likes.
+(5) At most one output will be the "change" `scriptPubKey` for the payer.
+Different operations require different outputs.
+
+## Payload Format
+
+Each Blockstack transaction in Bitcoin describes the name operation within an `OP_RETURN` output. It encodes name ownership, name fees, and payments as `scriptPubKey` outputs. The specific operations are described below.
+
+Each `OP_RETURN` payload *always* starts with the two-byte string `id` (called the "magic" bytes in this document), followed by a one-byte `op` that describes the operation.
+
+### NAME_PREORDER
+
+Op: `?`
+
+Description: This transaction commits to the *hash* of a name. It is the first
+transaction of two transactions that must be sent to register a name in BNS.
+
+Example: [6730ae09574d5935ffabe3dd63a9341ea54fafae62fde36c27738e9ee9c4e889](https://www.blocktrail.com/BTC/tx/6730ae09574d5935ffabe3dd63a9341ea54fafae62fde36c27738e9ee9c4e889)
+
+`OP_RETURN` wire format:
+```
+ 0 2 3 23 39
+ |-----|--|--------------------------------------------------|--------------|
+ magic op hash_name(name.ns_id,script_pubkey,register_addr) consensus hash
+```
+
+Inputs:
+* Payment `scriptSig`'s
+
+Outputs:
+* `OP_RETURN` payload
+* Payment `scriptPubkey` script for change
+* `p2pkh` `scriptPubkey` to the burn address (0x00000000000000000000000000000000000000)
+
+Notes:
+* `register_addr` is a base58check-encoded `ripemd160(sha256(pubkey))` (i.e. an address). This address **must not** have been used before in the underlying blockchain.
+* `script_pubkey` is either a `p2pkh` or `p2sh` compiled Bitcoin script for the payer's address.
+
+### NAME_REGISTRATION
+
+Op: `:`
+
+Description: This transaction reveals the name whose hash was announced by a
+previous `NAME_PREORDER`. It is the second of two transactions that must be
+sent to register a name in BNS.
+
+Example: [55b8b42fc3e3d23cbc0f07d38edae6a451dfc512b770fd7903725f9e465b2925](https://www.blocktrail.com/BTC/tx/55b8b42fc3e3d23cbc0f07d38edae6a451dfc512b770fd7903725f9e465b2925)
+
+`OP_RETURN` wire format (2 variations allowed):
+
+Variation 1:
+```
+ 0 2 3 39
+ |----|--|-----------------------------|
+ magic op name.ns_id (37 bytes)
+```
+
+Variation 2:
+```
+ 0 2 3 39 59
+ |----|--|----------------------------------|-------------------|
+ magic op name.ns_id (37 bytes, 0-padded) value
+```
+
+Inputs:
+* Payer `scriptSig`'s
+
+Outputs:
+* `OP_RETURN` payload
+* `scriptPubkey` for the owner's address
+* `scriptPubkey` for the payer's change
+
+Notes:
+
+* Variation 1 simply registers the name. Variation 2 will register the name and
+set a name value simultaneously. This is used in practice to set a zone file
+hash for a name without the extra `NAME_UPDATE` transaction.
+* Both variations are supported. Variation 1 was designed for the time when
+ Bitcoin only supported 40-byte `OP_RETURN` outputs.
+
+### NAME_RENEWAL
+
+Op: `:`
+
+Description: This transaction renews a name in BNS. The name must still be
+registered and not expired, and owned by the transaction sender.
+
+Example: [e543211b18e5d29fd3de7c0242cb017115f6a22ad5c6d51cf39e2b87447b7e65](https://www.blocktrail.com/BTC/tx/e543211b18e5d29fd3de7c0242cb017115f6a22ad5c6d51cf39e2b87447b7e65)
+
+`OP_RETURN` wire format (2 variations allowed):
+
+Variation 1:
+```
+ 0 2 3 39
+ |----|--|-----------------------------|
+ magic op name.ns_id (37 bytes)
+```
+
+Variation 2:
+```
+ 0 2 3 39 59
+ |----|--|----------------------------------|-------------------|
+ magic op name.ns_id (37 bytes, 0-padded) value
+```
+
+Inputs:
+
+* Payer `scriptSig`'s
+
+Outputs:
+
+* `OP_RETURN` payload
+* `scriptPubkey` for the owner's addess. This can be a different address than
+ the current name owner (in which case, the name is renewed and transferred).
+* `scriptPubkey` for the payer's change
+* `scriptPubkey` for the burn address (to pay the name cost)
+
+Notes:
+
+* This transaction is identical to a `NAME_REGISTRATION`, except for the presence of the fourth output that pays for the name cost (to the burn address).
+* Variation 1 simply renews the name. Variation 2 will both renew the name and
+ set a new name value (in practice, the hash of a new zone file).
+* Both variations are supported. Variation 1 was designed for the time when
+ Bitcoin only supported 40-byte `OP_RETURN` outputs.
+* This operation can be used to transfer a name to a new address by setting the
+ second output (the first `scriptPubkey`) to be the `scriptPubkey` of the new
+ owner key.
+
+### NAME_UPDATE
+
+Op: `+`
+
+Description: This transaction sets the name state for a name to the given
+`value`. In practice, this is used to announce new DNS zone file hashes to the [Atlas
+network]({{ site.baseurl }}/core/atlas/overview.html).
+
+Example: [e2029990fa75e9fc642f149dad196ac6b64b9c4a6db254f23a580b7508fc34d7](https://www.blocktrail.com/BTC/tx/e2029990fa75e9fc642f149dad196ac6b64b9c4a6db254f23a580b7508fc34d7)
+
+`OP_RETURN` wire format:
+```
+ 0 2 3 19 39
+ |-----|--|-----------------------------------|-----------------------|
+ magic op hash128(name.ns_id,consensus hash) zone file hash
+```
+
+Note that `hash128(name.ns_id, consensus hash)` is the first 16 bytes of a SHA256 hash over the name concatenated to the hexadecimal string of the consensus hash (not the bytes corresponding to that hex string).
+See the [Method Glossary](#method-glossary) below.
+
+Example: `hash128("jude.id" + "8d8762c37d82360b84cf4d87f32f7754") == "d1062edb9ec9c85ad1aca6d37f2f5793"`.
+
+The 20 byte zone file hash is computed from zone file data by using `ripemd160(sha56(zone file data))`
+
+Inputs:
+* owner `scriptSig`
+* payment `scriptSig`'s
+
+Outputs:
+* `OP_RETURN` payload
+* owner's `scriptPubkey`
+* payment `scriptPubkey` change
+
+### NAME_TRANSFER
+
+Op: `>`
+
+Description: This transaction changes the public key hash that owns the name in
+BNS.
+
+Example: [7a0a3bb7d39b89c3638abc369c85b5c028d0a55d7804ba1953ff19b0125f3c24](https://www.blocktrail.com/BTC/tx/7a0a3bb7d39b89c3638abc369c85b5c028d0a55d7804ba1953ff19b0125f3c24)
+
+`OP_RETURN` wire format:
+```
+ 0 2 3 4 20 36
+ |-----|--|----|-------------------|---------------|
+ magic op keep hash128(name.ns_id) consensus hash
+ data?
+```
+
+Inputs:
+
+* Owner `scriptSig`
+* Payment `scriptSig`'s
+
+Outputs:
+
+* `OP_RETURN` payload
+* new name owner's `scriptPubkey`
+* old name owner's `scriptPubkey`
+* payment `scriptPubkey` change
+
+Notes:
+
+* The `keep data?` byte controls whether or not the name's 20-byte value is preserved. This value is either `>` to preserve it, or `~` to delete it.
+
+### NAME_REVOKE
+
+Op: `~`
+
+Description: This transaction destroys a registered name. Its name state value
+in BNS will be cleared, and no further transactions will be able to affect the
+name until it expires (if its namespace allows it to expire at all).
+
+Example: [eb2e84a45cf411e528185a98cd5fb45ed349843a83d39fd4dff2de47adad8c8f](https://www.blocktrail.com/BTC/tx/eb2e84a45cf411e528185a98cd5fb45ed349843a83d39fd4dff2de47adad8c8f)
+
+`OP_RETURN` wire format:
+```
+ 0 2 3 39
+ |----|--|-----------------------------|
+ magic op name.ns_id (37 bytes)
+```
+
+Inputs:
+
+* owner `scriptSig`
+* payment `scriptSig`'s
+
+Outputs:
+
+* `OP_RETURN` payload
+* owner `scriptPubkey`
+* payment `scriptPubkey` change
+
+### ANNOUNCE
+
+Op: `#`
+
+Description: This transaction does not affect any names in BNS, but it allows a
+user to send a message to other BNS nodes. In order for the message to be
+received, the following must be true:
+
+* The sender must have a BNS name
+* The BNS nodes must list the sender's BNS name as being a "trusted message
+ sender"
+* The message must have already been propagated through the [Atlas
+ network]({{ site.baseurl }}/core/atlas/overview.html). This transaction references it by content hash.
+
+`OP_RETURN` wire format:
+
+```
+ 0 2 3 23
+ |----|--|-----------------------------|
+ magic op ripemd160(sha256(message))
+```
+
+Inputs:
+
+* The payer `scriptSig`'s
+
+Outputs:
+
+* `OP_RETURN` payload
+* change `scriptPubKey`
+
+Notes:
+
+* The payer key should be an owner key for an existing name, since Blockstack users can subscribe to announcements from specific name-owners.
+
+### NAMESPACE_PREORDER
+
+Op: `*`
+
+Description: This transaction announces the *hash* of a new namespace. It is the
+first of three transactions that must be sent to create a namespace.
+
+Example: [5f00b8e609821edd6f3369ee4ee86e03ea34b890e242236cdb66ef6c9c6a1b28](https://www.blocktrail.com/BTC/tx/5f00b8e609821edd6f3369ee4ee86e03ea34b890e242236cdb66ef6c9c6a1b28)
+
+`OP_RETURN` wire format:
+```
+ 0 2 3 23 39
+ |-----|---|-----------------------------------------|----------------|
+ magic op hash_name(ns_id,script_pubkey,reveal_addr) consensus hash
+```
+
+Inputs:
+
+* Namespace payer `scriptSig`
+
+Outputs:
+
+* `OP_RETURN` payload
+* Namespace payer `scriptPubkey` change address
+* `p2pkh` script to the burn address `1111111111111111111114oLvT2`, whose public key hash is 0x00000000000000000000000000000000
+
+Notes:
+
+* The `reveal_addr` field is the address of the namespace revealer public key. The revealer private key will be used to generate `NAME_IMPORT` transactions.
+
+### NAMESPACE_REVEAL
+
+Op: `&`
+
+Description: This transaction reveals the namespace ID and namespace rules
+for a previously-anounced namespace hash (sent by a previous `NAMESPACE_PREORDER`).
+
+Example: [ab54b1c1dd5332dc86b24ca2f88b8ca0068485edf0c322416d104c5b84133a32](https://www.blocktrail.com/BTC/tx/ab54b1c1dd5332dc86b24ca2f88b8ca0068485edf0c322416d104c5b84133a32)
+
+`OP_RETURN` wire format:
+```
+ 0 2 3 7 8 9 10 11 12 13 14 15 16 17 18 20 39
+ |-----|---|--------|-----|-----|----|----|----|----|----|-----|-----|-----|--------|----------|-------------------------|
+ magic op life coeff. base 1-2 3-4 5-6 7-8 9-10 11-12 13-14 15-16 nonalpha version namespace ID
+ bucket exponents no-vowel
+ discounts
+```
+
+Inputs:
+
+* Namespace payer `scriptSig`s
+
+Outputs:
+
+* `OP_RETURN` payload
+* namespace revealer `scriptPubkey`
+* namespace payer change `scriptPubkey`
+
+Notes:
+
+* This transaction must be sent within 1 day of the `NAMESPACE_PREORDER`
+* The second output (with the namespace revealer) **must** be a `p2pkh` script
+* The address of the second output **must** be the `reveal_addr` in the `NAMESPACE_PREORDER`
+
+Pricing:
+
+The rules for a namespace are as follows:
+
+ * a name can fall into one of 16 buckets, measured by length. Bucket 16 incorporates all names at least 16 characters long.
+ * the pricing structure applies a multiplicative penalty for having numeric characters, or punctuation characters.
+ * the price of a name in a bucket is ((coeff) * (base) ^ (bucket exponent)) / ((numeric discount multiplier) * (punctuation discount multiplier))
+
+Example:
+* base = 10
+* coeff = 2
+* nonalpha discount: 10
+* no-vowel discount: 10
+* buckets 1, 2: 9
+* buckets 3, 4, 5, 6: 8
+* buckets 7, 8, 9, 10, 11, 12, 13, 14: 7
+* buckets 15, 16+:
+
+With the above example configuration, the following are true:
+
+* The price of "john" would be 2 * 10^8, since "john" falls into bucket 4 and has no punctuation or numerics.
+* The price of "john1" would be 2 * 10^6, since "john1" falls into bucket 5 but has a number (and thus receives a 10x discount)
+* The price of "john_1" would be 2 * 10^6, since "john_1" falls into bucket 6 but has a number and punctuation (and thus receives a 10x discount)
+* The price of "j0hn_1" would be 2 * 10^5, since "j0hn_1" falls into bucket 6 but has a number and punctuation and lacks vowels (and thus receives a 100x discount)
+
+
+### NAME_IMPORT
+
+Op: `;`
+
+Description: This transaction registers a name and some name state into a
+namespace that has been revealed, but not been launched. Only the namespace
+creator can import names. See the [namespace creation section]({{ site.baseurl }}/core/naming/namespaces.html) for details.
+
+Example: [c698ac4b4a61c90b2c93dababde867dea359f971e2efcf415c37c9a4d9c4f312](https://www.blocktrail.com/BTC/tx/c698ac4b4a61c90b2c93dababde867dea359f971e2efcf415c37c9a4d9c4f312)
+
+`OP_RETURN` wire format:
+```
+ 0 2 3 39
+ |----|--|-----------------------------|
+ magic op name.ns_id (37 bytes)
+```
+
+Inputs:
+
+* The namespace reveal `scriptSig` (with the namespace revealer's public key), or one of its first 300 extended public keys
+* Any payment inputs
+
+Outputs:
+
+* `OP_RETURN` payload
+* recipient `scriptPubKey`
+* zone file hash (using the 20-byte hash in a standard `p2pkh` script)
+* payment change `scriptPubKey`
+
+Notes:
+
+* These transactions can only be sent between the `NAMESPACE_REVEAL` and `NAMESPACE_READY`.
+* The first `NAME_IMPORT` transaction **must** have a `scriptSig` input that matches the `NAMESPACE_REVEAL`'s second output (i.e. the reveal output).
+* Any subsequent `NAME_IMPORT` transactions **may** have a `scriptSig` input whose public key is one of the first 300 extended public keys from the `NAMESPACE_REVEAL`'s `scriptSig` public key.
+
+### NAMESPACE_READY
+
+Op: `!`
+
+Description: This transaction launches a namesapce. Only the namespace creator
+can send this transaction. Once sent, anyone can register names in the
+namespace.
+
+Example: [2bf9a97e3081886f96c4def36d99a677059fafdbd6bdb6d626c0608a1e286032](https://www.blocktrail.com/BTC/tx/2bf9a97e3081886f96c4def36d99a677059fafdbd6bdb6d626c0608a1e286032)
+
+`OP_RETURN` wire format:
+```
+
+ 0 2 3 4 23
+ |-----|--|--|------------|
+ magic op . ns_id
+```
+
+Inputs:
+* Namespace revealer's `scriptSig`s
+
+Outputs:
+* `OP_RETURN` payload
+* Change output to the namespace revealer's `p2pkh` script
+
+Notes:
+* This transaction must be sent within 1 year of the corresponding `NAMESPACE_REVEAL` to be accepted.
+
+## Method Glossary
+
+Some hashing primitives are used to construct the wire-format representation of each name operation. They are enumerated here:
+
+```
+B40_REGEX = '^[a-z0-9\-_.+]*$'
+
+def is_b40(s):
+ return isinstance(s, str) and re.match(B40_REGEX, s) is not None
+
+def b40_to_bin(s):
+ if not is_b40(s):
+ raise ValueError('{} must only contain characters in the b40 char set'.format(s))
+ return unhexlify(charset_to_hex(s, B40_CHARS))
+
+def hexpad(x):
+ return ('0' * (len(x) % 2)) + x
+
+def charset_to_hex(s, original_charset):
+ return hexpad(change_charset(s, original_charset, B16_CHARS))
+
+def bin_hash160(s, hex_format=False):
+ """ s is in hex or binary format
+ """
+ if hex_format and is_hex(s):
+ s = unhexlify(s)
+ return hashlib.new('ripemd160', bin_sha256(s)).digest()
+
+def hex_hash160(s, hex_format=False):
+ """ s is in hex or binary format
+ """
+ if hex_format and is_hex(s):
+ s = unhexlify(s)
+ return hexlify(bin_hash160(s))
+
+def hash_name(name, script_pubkey, register_addr=None):
+ """
+ Generate the hash over a name and hex-string script pubkey.
+ Returns the hex-encoded string RIPEMD160(SHA256(x)), where
+ x is the byte string composed of the concatenation of the
+ binary
+ """
+ bin_name = b40_to_bin(name)
+ name_and_pubkey = bin_name + unhexlify(script_pubkey)
+
+ if register_addr is not None:
+ name_and_pubkey += str(register_addr)
+
+ # make hex-encoded hash
+ return hex_hash160(name_and_pubkey)
+
+def hash128(data):
+ """
+ Hash a string of data by taking its 256-bit sha256 and truncating it to the
+ first 16 bytes
+ """
+ return hexlify(bin_sha256(data)[0:16])
+```
diff --git a/_data/navigation_usenew.yml b/_data/navigation_usenew.yml
index 271a6ffe..5fdf793f 100644
--- a/_data/navigation_usenew.yml
+++ b/_data/navigation_usenew.yml
@@ -1,5 +1,12 @@
+- title: Browser
- docs:
- - browser/ids-introduction
- browser/browser-introduction
- - browser/purchase-id
+ - browser/local_browser
+
+- title: Identity
+- docs:
+ - browser/ids-introduction
+
+- title: Reference
+- docs:
- browser/faq_general
diff --git a/_includes/head.html b/_includes/head.html
index 7da0e70a..30f5ab01 100644
--- a/_includes/head.html
+++ b/_includes/head.html
@@ -2,7 +2,8 @@
- {% seo %}
+ {{ page.title | escape }}
+ {% seo title=false %}
diff --git a/_includes/seo.html b/_includes/seo.html
new file mode 100644
index 00000000..e69de29b
diff --git a/_ios/.svn/entries b/_ios/.svn/entries
new file mode 100644
index 00000000..48082f72
--- /dev/null
+++ b/_ios/.svn/entries
@@ -0,0 +1 @@
+12
diff --git a/_ios/.svn/format b/_ios/.svn/format
new file mode 100644
index 00000000..48082f72
--- /dev/null
+++ b/_ios/.svn/format
@@ -0,0 +1 @@
+12
diff --git a/_ios/.svn/pristine/1a/1aaccf323aea42d9ad6957411e4d6869c7fd591f.svn-base b/_ios/.svn/pristine/1a/1aaccf323aea42d9ad6957411e4d6869c7fd591f.svn-base
new file mode 100644
index 00000000..e00e985b
Binary files /dev/null and b/_ios/.svn/pristine/1a/1aaccf323aea42d9ad6957411e4d6869c7fd591f.svn-base differ
diff --git a/_ios/.svn/pristine/2b/2bd64b689357b5e6639ab872c6f76449415f87a2.svn-base b/_ios/.svn/pristine/2b/2bd64b689357b5e6639ab872c6f76449415f87a2.svn-base
new file mode 100644
index 00000000..134d062d
Binary files /dev/null and b/_ios/.svn/pristine/2b/2bd64b689357b5e6639ab872c6f76449415f87a2.svn-base differ
diff --git a/_ios/.svn/pristine/41/410814802457e751ef97090c0813861c8e2234c9.svn-base b/_ios/.svn/pristine/41/410814802457e751ef97090c0813861c8e2234c9.svn-base
new file mode 100644
index 00000000..081d5050
Binary files /dev/null and b/_ios/.svn/pristine/41/410814802457e751ef97090c0813861c8e2234c9.svn-base differ
diff --git a/_ios/.svn/pristine/55/556fd22cb260be752d9e0976955a611765b260f1.svn-base b/_ios/.svn/pristine/55/556fd22cb260be752d9e0976955a611765b260f1.svn-base
new file mode 100644
index 00000000..ed8d7fa7
Binary files /dev/null and b/_ios/.svn/pristine/55/556fd22cb260be752d9e0976955a611765b260f1.svn-base differ
diff --git a/_ios/.svn/pristine/69/6904a6aefddb85cad5d15e62626e6ddee00b5381.svn-base b/_ios/.svn/pristine/69/6904a6aefddb85cad5d15e62626e6ddee00b5381.svn-base
new file mode 100644
index 00000000..e8f271fa
Binary files /dev/null and b/_ios/.svn/pristine/69/6904a6aefddb85cad5d15e62626e6ddee00b5381.svn-base differ
diff --git a/_ios/.svn/pristine/6b/6bbb57e8973ee164a4f7dfb71fe008ad2b0776b3.svn-base b/_ios/.svn/pristine/6b/6bbb57e8973ee164a4f7dfb71fe008ad2b0776b3.svn-base
new file mode 100644
index 00000000..914b26e5
Binary files /dev/null and b/_ios/.svn/pristine/6b/6bbb57e8973ee164a4f7dfb71fe008ad2b0776b3.svn-base differ
diff --git a/_ios/.svn/pristine/77/77c43e1cf4bed18d00c9e65e0c547fde1ba4688a.svn-base b/_ios/.svn/pristine/77/77c43e1cf4bed18d00c9e65e0c547fde1ba4688a.svn-base
new file mode 100644
index 00000000..243615bb
Binary files /dev/null and b/_ios/.svn/pristine/77/77c43e1cf4bed18d00c9e65e0c547fde1ba4688a.svn-base differ
diff --git a/_ios/.svn/pristine/82/820f9b4e801f2317a04c0d9a06d6bbb0e7b56364.svn-base b/_ios/.svn/pristine/82/820f9b4e801f2317a04c0d9a06d6bbb0e7b56364.svn-base
new file mode 100644
index 00000000..00e77f69
Binary files /dev/null and b/_ios/.svn/pristine/82/820f9b4e801f2317a04c0d9a06d6bbb0e7b56364.svn-base differ
diff --git a/_ios/.svn/pristine/87/8723aa418cae14b8126b8722e8dfdc1a683a58dd.svn-base b/_ios/.svn/pristine/87/8723aa418cae14b8126b8722e8dfdc1a683a58dd.svn-base
new file mode 100644
index 00000000..2003f793
Binary files /dev/null and b/_ios/.svn/pristine/87/8723aa418cae14b8126b8722e8dfdc1a683a58dd.svn-base differ
diff --git a/_ios/.svn/pristine/99/995beb2189dcaa16e860b40abfdaff72aee54a12.svn-base b/_ios/.svn/pristine/99/995beb2189dcaa16e860b40abfdaff72aee54a12.svn-base
new file mode 100644
index 00000000..9f1876fd
Binary files /dev/null and b/_ios/.svn/pristine/99/995beb2189dcaa16e860b40abfdaff72aee54a12.svn-base differ
diff --git a/_ios/.svn/pristine/a4/a4224b8a5f906d9285bc9ca288625a9f2db06455.svn-base b/_ios/.svn/pristine/a4/a4224b8a5f906d9285bc9ca288625a9f2db06455.svn-base
new file mode 100644
index 00000000..81f7997e
Binary files /dev/null and b/_ios/.svn/pristine/a4/a4224b8a5f906d9285bc9ca288625a9f2db06455.svn-base differ
diff --git a/_ios/.svn/pristine/b3/b33a74743d047d981a8d69b7b72e8672a55db868.svn-base b/_ios/.svn/pristine/b3/b33a74743d047d981a8d69b7b72e8672a55db868.svn-base
new file mode 100644
index 00000000..96282709
Binary files /dev/null and b/_ios/.svn/pristine/b3/b33a74743d047d981a8d69b7b72e8672a55db868.svn-base differ
diff --git a/_ios/.svn/pristine/c4/c4aafd61b7349848488ea22f0c6f1fc8637877af.svn-base b/_ios/.svn/pristine/c4/c4aafd61b7349848488ea22f0c6f1fc8637877af.svn-base
new file mode 100644
index 00000000..b222e37c
Binary files /dev/null and b/_ios/.svn/pristine/c4/c4aafd61b7349848488ea22f0c6f1fc8637877af.svn-base differ
diff --git a/_ios/.svn/pristine/ce/ce126ffc29f6a374f813a5cf0a0f2ac25739b92b.svn-base b/_ios/.svn/pristine/ce/ce126ffc29f6a374f813a5cf0a0f2ac25739b92b.svn-base
new file mode 100644
index 00000000..c8d8f4be
Binary files /dev/null and b/_ios/.svn/pristine/ce/ce126ffc29f6a374f813a5cf0a0f2ac25739b92b.svn-base differ
diff --git a/_ios/.svn/pristine/d6/d64d3616b97aba1cd1088f7ac2019d25ffb621b5.svn-base b/_ios/.svn/pristine/d6/d64d3616b97aba1cd1088f7ac2019d25ffb621b5.svn-base
new file mode 100644
index 00000000..f2c7f08d
Binary files /dev/null and b/_ios/.svn/pristine/d6/d64d3616b97aba1cd1088f7ac2019d25ffb621b5.svn-base differ
diff --git a/_ios/.svn/pristine/e1/e1a03d47513657db55eda3c67530b924ae5395b9.svn-base b/_ios/.svn/pristine/e1/e1a03d47513657db55eda3c67530b924ae5395b9.svn-base
new file mode 100644
index 00000000..28352bd3
--- /dev/null
+++ b/_ios/.svn/pristine/e1/e1a03d47513657db55eda3c67530b924ae5395b9.svn-base
@@ -0,0 +1,700 @@
+---
+layout: learn
+permalink: /:collection/:path.html
+---
+# iOS SDK Tutorial (Pre-release)
+{:.no_toc}
+
+This tutorial teaches you how to create a decentralized application using
+Blockstack's iOS SDK using the following content:
+
+* TOC
+{:toc}
+
+This tutorial was extensively tested using XCode 9.3 on a MacBook Air
+running High Sierra 10.13.4. If your environment is different, you may encounter
+slight or even major discrepancies when performing the procedures in this
+tutorial. Please [join the Blockstack community Slack](https://slofile.com/slack/blockstack) and post questions or comments to
+the `#support` channel.
+
+Finally, this tutorial is written for all levels from the beginner to the most
+experienced. For best results, beginners should follow the guide as written. It
+is expected that the fast or furiously brilliant will skip ahead and improvise
+on this material at will. God speed one and all.
+
+If you prefer, you can skip working through the tutorial all together. Instead,
+you can [download the final project code](#) and import it
+into XCode to review it.
+
+## Understand the sample application flow
+
+When complete, the sample application is a simple `hello-world` intended for use
+on an iOS phone.
+
+![](images/final-app.png)
+
+Only users with an existing `blockstack.id` can run your
+final sample application. When complete, users interact with the sample
+application by doing the following:
+
+![](images/app-flow.png)
+
+## Set up your environment
+
+This sample application requires two code bases, a BlockStack `hello-blockstack` web
+application and a `hello-ios` iOS application. You use the iOS application to run the
+web application on an iOS device.
+
+Before you start developing the sample, there are a few elements you need in
+your environment.
+
+### Install XCode
+
+If you are an experienced iOS developer and already have an iOS
+development environment on your workstation, you can use that and skip this
+step. However, you may need to adjust the remaining instructions for your
+environment.
+
+Follow the installation instructions to [download and XCode](https://developer.apple.com/xcode/) for your operating system.
+Depending on your network connection, this can take between 15-30 minutes.
+
+### Do you have npm?
+
+The Blockstack code in this tutorial relies on the `npm` dependency manager.
+Before you begin, verify you have installed `npm` using the `which` command to
+verify.
+
+```bash
+$ which npm
+/usr/local/bin/npm
+```
+
+If you don't find `npm` in your system, [install
+it](https://www.npmjs.com/get-npm).
+
+### Install the CocoaPods 1.6.0.beta.1 dependency manager
+
+The sample application only runs on devices with iOS 11.0 or higher. You install
+the Blockstack iOS SDK through the CocoaPods. Cocoapods is a dependency manager
+for Swift and Objective-C Cocoa projects. It’s a simple, user friendly way to
+use libraries from the community in your project.
+
+You must use the `1.6.0.beta.1` version of CocoaPods or newer to avoid an
+incapability between Cocoapods and XCode. Before starting the tutorial, confirm
+you have installed CocoaPods.
+
+```bash
+$ pod --version
+1.6.0.beta.1
+```
+
+If you don't have the CocoaPods beta version, install it:
+
+```bash
+sudo gem install cocoapods -v 1.6.0.beta.1
+```
+
+### Use npm to install Yeoman and the Blockstack App Generator
+
+You use `npm` to install Yeoman. Yeoman is a generic scaffolding system that
+helps users rapidly start new projects and streamline the maintenance of
+existing projects.
+
+
+1. Install Yeoman.
+
+ ```bash
+ npm install -g yo
+ ```
+2. Install the Blockstack application generator.
+
+ ```bash
+ npm install -g generator-blockstack
+ ```
+## Build the Blockstack hello-world
+
+In this section, you build a Blockstack `hello-world` application. Then, you
+modify the `hello-world` to interact with the iOS app via a redirect.
+
+### Generate and launch your hello-blockstack application
+
+In this section, you build an initial React.js application called
+`hello-blockstack`.
+
+1. Create a `hello-blockstack` directory.
+
+ ```bash
+ mkdir hello-blockstack
+ ```
+
+2. Change into your new directory.
+
+ ```bash
+ cd hello-blockstack
+ ```
+
+3. Use Yeoman and the Blockstack application generator to create your initial `hello-blockstack` application.
+
+ ```bash
+ yo blockstack:react
+ ```
+
+ You should see several interactive prompts.
+
+ ```bash
+ $ yo blockstack:react
+ ==========================================================================
+ We are constantly looking for ways to make yo better!
+ May we anonymously report usage statistics to improve the tool over time?
+ More info: https://github.com/yeoman/insight & http://yeoman.io
+ ========================================================================== No
+
+ _-----_ ╭──────────────────────────╮
+ | | │ Welcome to the │
+ |--(o)--| │ Blockstack app │
+ `---------´ │ generator! │
+ ( _´U`_ ) ╰──────────────────────────╯
+ /___A___\ /
+ | ~ |
+ __'.___.'__
+ ´ ` |° ´ Y `
+
+ ? Are you ready to build a Blockstack app in React? (Y/n)
+ ```
+
+4. Respond to the prompts to populate the initial app.
+
+ After the process completes successfully, you see a prompt similar to the following:
+
+ ```bash
+ [fsevents] Success:
+ "/Users/theuser/repos/hello-blockstack/node_modules/fsevents/lib/binding/Release/node-v59-darwin-x64/fse.node"
+ is installed via remote npm notice created a lockfile as package-lock.json.
+ You should commit this file. added 1060 packages in 26.901s
+ ```
+
+5. Run the initial application.
+
+ ```bash
+ npm start
+
+ > hello-blockstack@0.0.0 start /Users/moxiegirl/repos/hello-blockstack
+ > webpack-dev-server
+
+ Project is running at http://localhost:8080/
+ webpack output is served from /
+ 404s will fallback to /index.html
+ Hash: 4d2312ba236a4b95dc3a
+ Version: webpack 2.7.0
+ Time: 2969ms
+ Asset Size Chunks Chunk Names
+ ....
+ Child html-webpack-plugin for "index.html":
+ chunk {0} index.html 541 kB [entry] [rendered]
+ [0] ./~/lodash/lodash.js 540 kB {0} [built]
+ [1] ./~/html-webpack-plugin/lib/loader.js!./src/index.html 533 bytes {0} [built]
+ [2] (webpack)/buildin/global.js 509 bytes {0} [built]
+ [3] (webpack)/buildin/module.js 517 bytes {0} [built]
+ webpack: Compiled successfully.
+ ```
+
+ At this point, the browser is running a Blockstack server on your local host.
+
+6. Navigate to `https://localhost:8080` with your browser to display the
+ application.
+
+ ![](images/blockstack-signin.png)
+
+ This local instances is for testing your applications only.
+
+7. Choose **Sign in with Blockstack**
+
+ The system displays a prompt allowing you to create a new Blockstack ID or restore an existing one.
+
+ ![](images/create-restore.png)
+
+8. Follow the prompts appropriate to your situation.
+
+ If you are restoring an existing ID, you may see a prompt about your user
+ being nameless, ignore it. At this point you have only a single application
+ on your test server. So, you should see this single application, with your
+ own `blockstack.id` display name, once you are signed in:
+
+ ![](images/running-app.png)
+
+
+### Add a redirect end point to your application
+
+When a user opens the webapp from the Blockstack browser on an iOS phone,
+you want the web app to redirect the user to your iOS application. The work
+you do here will allow it.
+
+1. From the terminal command line, change directory to your web
+application directory.
+
+2. Create a `public` directory.
+
+ ```bash
+ $ mkdir public
+ ```
+
+2. Use the `touch` command to add a redirect endpoint to your application.
+
+ This endpoint on the web version of your app will redirect iOS users back
+ to your mobile app.
+
+ ```bash
+ $ touch public/redirect.html
+ ```
+
+3. Open `redirect.html` and add code to the endpoint.
+
+ ```
+
+
+
+ Hello, Blockstack!
+
+
+
+
+ ```
+
+ Blockstack apps are identified by their domain names. The endpoint will
+ receive a get request with the query parameter `authResponse=XXXX` and
+ should redirect the browser to `myblockstackapp:XXXX`.
+
+ `myblockstackapp:` is custom protocol handler. The handler should be unique
+ to your application. Your app's web-based authentication uses this handler
+ to redirect the user back to your iOS app. Later, you'll add a reference
+ to this handler in your iOS application.
+
+5. Close and save the `redirect.html` file.
+6. Ensure your Blockstack app compiles successfully.
+
+ The `npm` process should detect and compile your change.
+
+## Build the hello-blockstack-ios
+
+Now, you build an iOS application that can access and run your Blockstack web
+application on a mobile device.
+
+### Create an XCode Project
+
+This tutorial uses XCode 9.3, you can use another version but be aware that some
+menu items and therefore these procedures may be differœent on your version.
+
+1. Launch the XCode interface.
+2. Choose **Create new XCode project**.
+3. Select **iOS**.
+4. Select **Single View App**.
+
+ ![](images/single-view-app.png)
+
+5. **Choose options for your new project** for your project.
+
+ ![](images/choose-new-options.png)
+
+6. Press **Next**.
+
+ The system prompts you for a location to store your code.
+
+7. Save your project.
+8. Close XCode.
+
+
+### Add and edit a Podfile
+
+To use CocoaPods you need to define the XCode target to link them to.
+So for example if you are writing an iOS app, it would be the name of your app.
+Create a target section by writing target '$TARGET_NAME' do and an end a few
+lines after.
+
+1. Open a terminal window on your workstation.
+2. Navigate to and change directory into the root of your project directory.
+
+ ```swift
+ $ cd hello-blockstack-ios
+ ```
+3. Create a Podfile.
+
+ ```bash
+ $ pod init
+ ```
+
+ The command creates a `Podfile` in the directory.
+
+4. Open the `Podfile` for editing.
+5. Add a line stating the Blockstack dependency.
+
+ ```
+ # Uncomment the next line to define a global platform for your project
+ # platform :ios, '9.0'
+
+ target 'hello-blockstack-ios' do
+ # Comment the next line if you're not using Swift and don't want to use dynamic frameworks
+ use_frameworks!
+
+ # Pods for hello-blockstack-ios
+ pod 'Blockstack'
+
+ target 'hello-blockstack-iosTests' do
+ inherit! :search_paths
+ # Pods for testing
+ end
+ end
+ ```
+
+8. Save and close the `Podfile`.
+
+### Install Blockstack SDK and open the pod project
+
+1. Close your new XCode project.
+2. Change to the root of your `hello-blockstack-is` project.
+3. Initialize the project with Cocoapods.
+
+ ```
+ $ pod install
+ Analyzing dependencies
+ Downloading dependencies
+ Installing Blockstack (0.2.0)
+ Installing CryptoSwift (0.11.0)
+ Generating Pods project
+ Integrating client project
+
+ [!] Please close any current XCode sessions and use `hello-blockstack-ios.xcworkspace` for this project from now on.
+ Sending stats
+ Pod installation complete! There is 1 dependency from the Podfile and 2 total pods installed.
+
+ [!] Automatically assigning platform `ios` with version `11.4` on target `hello-blockstack-ios` because no platform was specified. Please specify a platform for this target in your Podfile. See `https://guides.cocoapods.org/syntax/podfile.html#platform`.
+ ```
+
+ This command creates a number of files
+
+4. Review the files that the `pod` installation created:
+
+ ```bash
+ $ ls
+ Podfile hello-blockstack-ios hello-blockstack-iosTests
+ Podfile.lock hello-blockstack-ios.xcodeproj
+ Pods hello-blockstack-ios.xcworkspace
+ ```
+5. Start XCode and choose **Open another project**.
+6. Choose the `.xcworkspace` file created in your project folder.
+
+ ![](images/open-xcworkspace.png)
+
+ When you open the workspace you'll see a warning indicator at the top in the
+ project title.
+
+7. Click the signal to reveal the warning.
+8. Click **Update to recommented settings**.
+
+ ![](images/indicator.png)
+
+9. Choose **Perform Changes** and **Continue** when prompted.
+
+ The indicator disappears.
+
+### Choose a custom protocol handler
+
+You'll need to choose a custom protocol handler that is unique to your app. This
+is so that your app's web-based authentication `redirect.html` endpoint can redirect
+the user back to your iOS app. In this example, you use `myblockstackapp://`.
+
+1. Open the `.xcworkspace` file in XCode if it isn't open already.
+2. Select the top node of your project.
+1. Select the **Info** tab in XCode.
+2. Scroll to **URL Types** and press **+** (plus) sign.
+3. Enter an **Identifier** and **URL Schemes** value.
+4. Set the **Role** to **Editor**.
+
+ When you are done the type appears as follows:
+
+ ![](images/url-type.png)
+
+### Add a splash screen
+
+All iOS applications require a splash page.
+
+1. Select `Assets.xcassets`
+2. Move your cursor into the area below Appicon.
+3. Right click and choose **New Image Set**
+
+ ![](images/image-set-0.png)
+
+4. Download the Blockstack icon.
+
+ ![](images/blockstack-icon.png)
+
+5. Drag the downloaded file into the **3X** position in your new Images folder.
+
+ ![](images/image-set-1.png)
+
+6. Select the `LaunchScreen.storyboard`.
+7. Choose **Open As > Source Code**.
+
+ ![](images/open-as.png)
+
+8. Replace the content of the `` element with the following:
+
+ ```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ```
+
+9. Immediately after scenes but before the close of the `` tag add the following ``.
+
+ ```xml
+
+
+
+
+ ```
+
+10. Choose **Run > Run app** in the emulator.
+
+ The emulator now contains a new splash screen.
+
+ ![](images/splash.png)
+
+
+### Update the Main.storyboard
+
+Rather than have you build up your own UI, this section has you copy and paste a layout into the XML file source code for the **Main.storyboard** file.
+
+1. Select the `Main.storyboard` file.
+2. Chooose **Open As > Source Code**
+
+ The `blockstack-example/blockstack-example/Base.lproj/Main.storyboard` file
+ defines the graphical elements. Some elements are required before you can
+ functionality to your code.
+
+3. Within the `` element, replace the existing `` subelement with the following:
+
+ ```xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ```
+
+### Add the UI variables to the ViewController file.
+
+In this section, you edit the `ViewController.swift` file using the storyboard as a starting point.
+
+1. Select the **Main.storyboard** and choose **Open As > Interface Builder - storyboard**.
+
+ ![](images/main-storyboard.png)
+
+2. With the interface builder open, display the `ViewController.swift` file in the rigth panel.
+
+ ![](images/view-editors.gif)
+
+4. In the storyboard, select the **Sign into Blockstack** button.
+
+5. Control-drag from the button to the code display in the editor on the right, stopping the drag at the line below controller's opening statement.
+
+ ![](images/add-action.gif)
+
+6. Repeat this process with the storyboard's purple **hello-blockstack-ios** label.
+
+ When you are done, your 'ViewController' file contains the following variables:
+
+ ```swift
+ class ViewController: UIViewController {
+
+ @IBOutlet var nameLabel: UILabel!
+ @IBOutlet var signInButton: UIButton!
+ ```
+
+ And XCode has added two outlines to the `Main.storyboard` source.
+
+ ```xml
+
+
+
+
+ ```
+
+ Your connectors will have their own `destination` and `id` values.
+
+
+### Edit the ViewController.swift file
+
+Now, you are ready to connect your application with your Blockstack Web
+Application. Normally, after building your Web application you would have
+registred it with Blockstack and the app would be available on the Web. This
+example skips this registration step and uses an example application we've
+already created for you:
+
+`https://heuristic-brown-7a88f8.netlify.com/redirect.html`
+
+This web application already has a redirect in place for you. You'll reference
+this application in your mobile add for now. In XCode, do the following;
+
+
+1. Open the `ViewController.swift` file.
+2. Add an import both for `Blockstack` and for `SafariServices`.
+
+ ```
+ import UIKit
+ import Blockstack
+ import SafariServices
+ ```
+
+3. Just before the `didReceiveMemoryWarning` function a private `updateUI()` function.
+
+ This function takes care of loading the user data from Blockstack.
+
+ ```swift
+ private func updateUI() {
+ DispatchQueue.main.async {
+ if Blockstack.shared.isSignedIn() {
+ // Read user profile data
+ let retrievedUserData = Blockstack.shared.loadUserData()
+ print(retrievedUserData?.profile?.name as Any)
+ let name = retrievedUserData?.profile?.name ?? "Nameless Person"
+ self.nameLabel?.text = "Hello, \(name)"
+ self.nameLabel?.isHidden = false
+ self.signInButton?.setTitle("Sign Out", for: .normal)
+ print("UI update SIGNED_IN")
+ } else {
+ self.nameLabel?.text = "hello-blockstack-ios"
+ self.signInButton?.setTitle("Sign into Blockstack", for: .normal)
+ print("UI update SIGNED_OUT")
+ }
+ }
+ }
+ ```
+
+ The function uses the `Blockstack.shared.isSignedIn()` method to determine if
+ the user is already logged into Blockstack or not. It then uses the
+ `Blockstack.shared.loadUserData()` method to load the user data and update
+ the application display with the username.
+
+5. Replace the content of the `viewDidLoad()` function so that it calls this private function.
+
+ ```swift
+ override func viewDidLoad() {
+ super.viewDidLoad()
+ // Do any additional setup after loading the view, typically from a nib.
+ self.updateUI()
+ }
+ ```
+
+9. Create a 'signIn()' function that handles both sign in and out.
+
+ The function uses the `Blockstack.shared.signIn()` and
+ `Blockstack.shared.signOut()` methods to sign the user into the application.
+
+ ```swift
+ @IBAction func signIn(_ sender: UIButton) {
+ if Blockstack.shared.isSignedIn() {
+ print("Currently signed in so signing out.")
+ Blockstack.shared.signOut()
+ self.updateUI()
+ } else {
+ print("Currently signed out so signing in.")
+ // Address of deployed example web app
+ Blockstack.shared.signIn(redirectURI: "https://heuristic-brown-7a88f8.netlify.com/redirect.html",
+ appDomain: URL(string: "https://heuristic-brown-7a88f8.netlify.com")!) { authResult in
+ switch authResult {
+ case .success(let userData):
+ print("Sign in SUCCESS", userData.profile?.name as Any)
+ self.updateUI()
+ case .cancelled:
+ print("Sign in CANCELLED")
+ case .failed(let error):
+ print("Sign in FAILED, error: ", error ?? "n/a")
+ }
+ }
+ }
+
+ }
+ ```
+
+## Troubleshooting your build in XCode
+
+XCode builds can retain old data. To ensure your builds are clean, try the following:
+
+1. Reset the simulator by choosing **Hardware -> Erase all content and settings** from the menu.
+2. In XCode, clean the project by choosing **Product > Clean** from the menu or press 'Command + Shift + K' on your keyboard.
+3. Clean the build folder by pressing 'Command + Option + Shift + K' on your keyboard.
+4. Run the code on the simulator again.
diff --git a/_ios/.svn/pristine/ec/ec28305cabded3a21d65ddbc0e1aa5fc446567d3.svn-base b/_ios/.svn/pristine/ec/ec28305cabded3a21d65ddbc0e1aa5fc446567d3.svn-base
new file mode 100644
index 00000000..fa8b85a3
Binary files /dev/null and b/_ios/.svn/pristine/ec/ec28305cabded3a21d65ddbc0e1aa5fc446567d3.svn-base differ
diff --git a/_ios/.svn/pristine/f4/f46b7546eae669225bf3d9339962bd87f7a063d0.svn-base b/_ios/.svn/pristine/f4/f46b7546eae669225bf3d9339962bd87f7a063d0.svn-base
new file mode 100644
index 00000000..9838c05f
Binary files /dev/null and b/_ios/.svn/pristine/f4/f46b7546eae669225bf3d9339962bd87f7a063d0.svn-base differ
diff --git a/_ios/.svn/pristine/fe/fefe1360df9ba86053e901044f9713d3ee2b6207.svn-base b/_ios/.svn/pristine/fe/fefe1360df9ba86053e901044f9713d3ee2b6207.svn-base
new file mode 100644
index 00000000..6854281c
Binary files /dev/null and b/_ios/.svn/pristine/fe/fefe1360df9ba86053e901044f9713d3ee2b6207.svn-base differ
diff --git a/_ios/.svn/wc.db b/_ios/.svn/wc.db
new file mode 100644
index 00000000..de34d9f7
Binary files /dev/null and b/_ios/.svn/wc.db differ
diff --git a/_ios/.svn/wc.db-journal b/_ios/.svn/wc.db-journal
new file mode 100644
index 00000000..e69de29b
diff --git a/_ios/images/add-action.gif b/_ios/images/add-action.gif
new file mode 100644
index 00000000..6854281c
Binary files /dev/null and b/_ios/images/add-action.gif differ
diff --git a/_ios/images/app-flow.png b/_ios/images/app-flow.png
new file mode 100644
index 00000000..fa8b85a3
Binary files /dev/null and b/_ios/images/app-flow.png differ
diff --git a/_ios/images/blockstack-icon.png b/_ios/images/blockstack-icon.png
new file mode 100644
index 00000000..243615bb
Binary files /dev/null and b/_ios/images/blockstack-icon.png differ
diff --git a/_ios/images/blockstack-signin.png b/_ios/images/blockstack-signin.png
new file mode 100644
index 00000000..081d5050
Binary files /dev/null and b/_ios/images/blockstack-signin.png differ
diff --git a/_ios/images/choose-new-options.png b/_ios/images/choose-new-options.png
new file mode 100644
index 00000000..9f1876fd
Binary files /dev/null and b/_ios/images/choose-new-options.png differ
diff --git a/_ios/images/create-restore.png b/_ios/images/create-restore.png
new file mode 100644
index 00000000..914b26e5
Binary files /dev/null and b/_ios/images/create-restore.png differ
diff --git a/_ios/images/final-app.png b/_ios/images/final-app.png
new file mode 100644
index 00000000..81f7997e
Binary files /dev/null and b/_ios/images/final-app.png differ
diff --git a/_ios/images/image-set-0.png b/_ios/images/image-set-0.png
new file mode 100644
index 00000000..ed8d7fa7
Binary files /dev/null and b/_ios/images/image-set-0.png differ
diff --git a/_ios/images/image-set-1.png b/_ios/images/image-set-1.png
new file mode 100644
index 00000000..e8f271fa
Binary files /dev/null and b/_ios/images/image-set-1.png differ
diff --git a/_ios/images/indicator.png b/_ios/images/indicator.png
new file mode 100644
index 00000000..96282709
Binary files /dev/null and b/_ios/images/indicator.png differ
diff --git a/_ios/images/main-storyboard.png b/_ios/images/main-storyboard.png
new file mode 100644
index 00000000..e00e985b
Binary files /dev/null and b/_ios/images/main-storyboard.png differ
diff --git a/_ios/images/open-as.png b/_ios/images/open-as.png
new file mode 100644
index 00000000..00e77f69
Binary files /dev/null and b/_ios/images/open-as.png differ
diff --git a/_ios/images/open-xcworkspace.png b/_ios/images/open-xcworkspace.png
new file mode 100644
index 00000000..c8d8f4be
Binary files /dev/null and b/_ios/images/open-xcworkspace.png differ
diff --git a/_ios/images/running-app.png b/_ios/images/running-app.png
new file mode 100644
index 00000000..9838c05f
Binary files /dev/null and b/_ios/images/running-app.png differ
diff --git a/_ios/images/single-view-app.png b/_ios/images/single-view-app.png
new file mode 100644
index 00000000..f2c7f08d
Binary files /dev/null and b/_ios/images/single-view-app.png differ
diff --git a/_ios/images/splash.png b/_ios/images/splash.png
new file mode 100644
index 00000000..134d062d
Binary files /dev/null and b/_ios/images/splash.png differ
diff --git a/_ios/images/url-type.png b/_ios/images/url-type.png
new file mode 100644
index 00000000..b222e37c
Binary files /dev/null and b/_ios/images/url-type.png differ
diff --git a/_ios/images/view-editors.gif b/_ios/images/view-editors.gif
new file mode 100644
index 00000000..2003f793
Binary files /dev/null and b/_ios/images/view-editors.gif differ
diff --git a/_ios/tutorial.md b/_ios/tutorial.md
new file mode 100644
index 00000000..28352bd3
--- /dev/null
+++ b/_ios/tutorial.md
@@ -0,0 +1,700 @@
+---
+layout: learn
+permalink: /:collection/:path.html
+---
+# iOS SDK Tutorial (Pre-release)
+{:.no_toc}
+
+This tutorial teaches you how to create a decentralized application using
+Blockstack's iOS SDK using the following content:
+
+* TOC
+{:toc}
+
+This tutorial was extensively tested using XCode 9.3 on a MacBook Air
+running High Sierra 10.13.4. If your environment is different, you may encounter
+slight or even major discrepancies when performing the procedures in this
+tutorial. Please [join the Blockstack community Slack](https://slofile.com/slack/blockstack) and post questions or comments to
+the `#support` channel.
+
+Finally, this tutorial is written for all levels from the beginner to the most
+experienced. For best results, beginners should follow the guide as written. It
+is expected that the fast or furiously brilliant will skip ahead and improvise
+on this material at will. God speed one and all.
+
+If you prefer, you can skip working through the tutorial all together. Instead,
+you can [download the final project code](#) and import it
+into XCode to review it.
+
+## Understand the sample application flow
+
+When complete, the sample application is a simple `hello-world` intended for use
+on an iOS phone.
+
+![](images/final-app.png)
+
+Only users with an existing `blockstack.id` can run your
+final sample application. When complete, users interact with the sample
+application by doing the following:
+
+![](images/app-flow.png)
+
+## Set up your environment
+
+This sample application requires two code bases, a BlockStack `hello-blockstack` web
+application and a `hello-ios` iOS application. You use the iOS application to run the
+web application on an iOS device.
+
+Before you start developing the sample, there are a few elements you need in
+your environment.
+
+### Install XCode
+
+If you are an experienced iOS developer and already have an iOS
+development environment on your workstation, you can use that and skip this
+step. However, you may need to adjust the remaining instructions for your
+environment.
+
+Follow the installation instructions to [download and XCode](https://developer.apple.com/xcode/) for your operating system.
+Depending on your network connection, this can take between 15-30 minutes.
+
+### Do you have npm?
+
+The Blockstack code in this tutorial relies on the `npm` dependency manager.
+Before you begin, verify you have installed `npm` using the `which` command to
+verify.
+
+```bash
+$ which npm
+/usr/local/bin/npm
+```
+
+If you don't find `npm` in your system, [install
+it](https://www.npmjs.com/get-npm).
+
+### Install the CocoaPods 1.6.0.beta.1 dependency manager
+
+The sample application only runs on devices with iOS 11.0 or higher. You install
+the Blockstack iOS SDK through the CocoaPods. Cocoapods is a dependency manager
+for Swift and Objective-C Cocoa projects. It’s a simple, user friendly way to
+use libraries from the community in your project.
+
+You must use the `1.6.0.beta.1` version of CocoaPods or newer to avoid an
+incapability between Cocoapods and XCode. Before starting the tutorial, confirm
+you have installed CocoaPods.
+
+```bash
+$ pod --version
+1.6.0.beta.1
+```
+
+If you don't have the CocoaPods beta version, install it:
+
+```bash
+sudo gem install cocoapods -v 1.6.0.beta.1
+```
+
+### Use npm to install Yeoman and the Blockstack App Generator
+
+You use `npm` to install Yeoman. Yeoman is a generic scaffolding system that
+helps users rapidly start new projects and streamline the maintenance of
+existing projects.
+
+
+1. Install Yeoman.
+
+ ```bash
+ npm install -g yo
+ ```
+2. Install the Blockstack application generator.
+
+ ```bash
+ npm install -g generator-blockstack
+ ```
+## Build the Blockstack hello-world
+
+In this section, you build a Blockstack `hello-world` application. Then, you
+modify the `hello-world` to interact with the iOS app via a redirect.
+
+### Generate and launch your hello-blockstack application
+
+In this section, you build an initial React.js application called
+`hello-blockstack`.
+
+1. Create a `hello-blockstack` directory.
+
+ ```bash
+ mkdir hello-blockstack
+ ```
+
+2. Change into your new directory.
+
+ ```bash
+ cd hello-blockstack
+ ```
+
+3. Use Yeoman and the Blockstack application generator to create your initial `hello-blockstack` application.
+
+ ```bash
+ yo blockstack:react
+ ```
+
+ You should see several interactive prompts.
+
+ ```bash
+ $ yo blockstack:react
+ ==========================================================================
+ We are constantly looking for ways to make yo better!
+ May we anonymously report usage statistics to improve the tool over time?
+ More info: https://github.com/yeoman/insight & http://yeoman.io
+ ========================================================================== No
+
+ _-----_ ╭──────────────────────────╮
+ | | │ Welcome to the │
+ |--(o)--| │ Blockstack app │
+ `---------´ │ generator! │
+ ( _´U`_ ) ╰──────────────────────────╯
+ /___A___\ /
+ | ~ |
+ __'.___.'__
+ ´ ` |° ´ Y `
+
+ ? Are you ready to build a Blockstack app in React? (Y/n)
+ ```
+
+4. Respond to the prompts to populate the initial app.
+
+ After the process completes successfully, you see a prompt similar to the following:
+
+ ```bash
+ [fsevents] Success:
+ "/Users/theuser/repos/hello-blockstack/node_modules/fsevents/lib/binding/Release/node-v59-darwin-x64/fse.node"
+ is installed via remote npm notice created a lockfile as package-lock.json.
+ You should commit this file. added 1060 packages in 26.901s
+ ```
+
+5. Run the initial application.
+
+ ```bash
+ npm start
+
+ > hello-blockstack@0.0.0 start /Users/moxiegirl/repos/hello-blockstack
+ > webpack-dev-server
+
+ Project is running at http://localhost:8080/
+ webpack output is served from /
+ 404s will fallback to /index.html
+ Hash: 4d2312ba236a4b95dc3a
+ Version: webpack 2.7.0
+ Time: 2969ms
+ Asset Size Chunks Chunk Names
+ ....
+ Child html-webpack-plugin for "index.html":
+ chunk {0} index.html 541 kB [entry] [rendered]
+ [0] ./~/lodash/lodash.js 540 kB {0} [built]
+ [1] ./~/html-webpack-plugin/lib/loader.js!./src/index.html 533 bytes {0} [built]
+ [2] (webpack)/buildin/global.js 509 bytes {0} [built]
+ [3] (webpack)/buildin/module.js 517 bytes {0} [built]
+ webpack: Compiled successfully.
+ ```
+
+ At this point, the browser is running a Blockstack server on your local host.
+
+6. Navigate to `https://localhost:8080` with your browser to display the
+ application.
+
+ ![](images/blockstack-signin.png)
+
+ This local instances is for testing your applications only.
+
+7. Choose **Sign in with Blockstack**
+
+ The system displays a prompt allowing you to create a new Blockstack ID or restore an existing one.
+
+ ![](images/create-restore.png)
+
+8. Follow the prompts appropriate to your situation.
+
+ If you are restoring an existing ID, you may see a prompt about your user
+ being nameless, ignore it. At this point you have only a single application
+ on your test server. So, you should see this single application, with your
+ own `blockstack.id` display name, once you are signed in:
+
+ ![](images/running-app.png)
+
+
+### Add a redirect end point to your application
+
+When a user opens the webapp from the Blockstack browser on an iOS phone,
+you want the web app to redirect the user to your iOS application. The work
+you do here will allow it.
+
+1. From the terminal command line, change directory to your web
+application directory.
+
+2. Create a `public` directory.
+
+ ```bash
+ $ mkdir public
+ ```
+
+2. Use the `touch` command to add a redirect endpoint to your application.
+
+ This endpoint on the web version of your app will redirect iOS users back
+ to your mobile app.
+
+ ```bash
+ $ touch public/redirect.html
+ ```
+
+3. Open `redirect.html` and add code to the endpoint.
+
+ ```
+
+
+
+ Hello, Blockstack!
+
+
+
+
+ ```
+
+ Blockstack apps are identified by their domain names. The endpoint will
+ receive a get request with the query parameter `authResponse=XXXX` and
+ should redirect the browser to `myblockstackapp:XXXX`.
+
+ `myblockstackapp:` is custom protocol handler. The handler should be unique
+ to your application. Your app's web-based authentication uses this handler
+ to redirect the user back to your iOS app. Later, you'll add a reference
+ to this handler in your iOS application.
+
+5. Close and save the `redirect.html` file.
+6. Ensure your Blockstack app compiles successfully.
+
+ The `npm` process should detect and compile your change.
+
+## Build the hello-blockstack-ios
+
+Now, you build an iOS application that can access and run your Blockstack web
+application on a mobile device.
+
+### Create an XCode Project
+
+This tutorial uses XCode 9.3, you can use another version but be aware that some
+menu items and therefore these procedures may be differœent on your version.
+
+1. Launch the XCode interface.
+2. Choose **Create new XCode project**.
+3. Select **iOS**.
+4. Select **Single View App**.
+
+ ![](images/single-view-app.png)
+
+5. **Choose options for your new project** for your project.
+
+ ![](images/choose-new-options.png)
+
+6. Press **Next**.
+
+ The system prompts you for a location to store your code.
+
+7. Save your project.
+8. Close XCode.
+
+
+### Add and edit a Podfile
+
+To use CocoaPods you need to define the XCode target to link them to.
+So for example if you are writing an iOS app, it would be the name of your app.
+Create a target section by writing target '$TARGET_NAME' do and an end a few
+lines after.
+
+1. Open a terminal window on your workstation.
+2. Navigate to and change directory into the root of your project directory.
+
+ ```swift
+ $ cd hello-blockstack-ios
+ ```
+3. Create a Podfile.
+
+ ```bash
+ $ pod init
+ ```
+
+ The command creates a `Podfile` in the directory.
+
+4. Open the `Podfile` for editing.
+5. Add a line stating the Blockstack dependency.
+
+ ```
+ # Uncomment the next line to define a global platform for your project
+ # platform :ios, '9.0'
+
+ target 'hello-blockstack-ios' do
+ # Comment the next line if you're not using Swift and don't want to use dynamic frameworks
+ use_frameworks!
+
+ # Pods for hello-blockstack-ios
+ pod 'Blockstack'
+
+ target 'hello-blockstack-iosTests' do
+ inherit! :search_paths
+ # Pods for testing
+ end
+ end
+ ```
+
+8. Save and close the `Podfile`.
+
+### Install Blockstack SDK and open the pod project
+
+1. Close your new XCode project.
+2. Change to the root of your `hello-blockstack-is` project.
+3. Initialize the project with Cocoapods.
+
+ ```
+ $ pod install
+ Analyzing dependencies
+ Downloading dependencies
+ Installing Blockstack (0.2.0)
+ Installing CryptoSwift (0.11.0)
+ Generating Pods project
+ Integrating client project
+
+ [!] Please close any current XCode sessions and use `hello-blockstack-ios.xcworkspace` for this project from now on.
+ Sending stats
+ Pod installation complete! There is 1 dependency from the Podfile and 2 total pods installed.
+
+ [!] Automatically assigning platform `ios` with version `11.4` on target `hello-blockstack-ios` because no platform was specified. Please specify a platform for this target in your Podfile. See `https://guides.cocoapods.org/syntax/podfile.html#platform`.
+ ```
+
+ This command creates a number of files
+
+4. Review the files that the `pod` installation created:
+
+ ```bash
+ $ ls
+ Podfile hello-blockstack-ios hello-blockstack-iosTests
+ Podfile.lock hello-blockstack-ios.xcodeproj
+ Pods hello-blockstack-ios.xcworkspace
+ ```
+5. Start XCode and choose **Open another project**.
+6. Choose the `.xcworkspace` file created in your project folder.
+
+ ![](images/open-xcworkspace.png)
+
+ When you open the workspace you'll see a warning indicator at the top in the
+ project title.
+
+7. Click the signal to reveal the warning.
+8. Click **Update to recommented settings**.
+
+ ![](images/indicator.png)
+
+9. Choose **Perform Changes** and **Continue** when prompted.
+
+ The indicator disappears.
+
+### Choose a custom protocol handler
+
+You'll need to choose a custom protocol handler that is unique to your app. This
+is so that your app's web-based authentication `redirect.html` endpoint can redirect
+the user back to your iOS app. In this example, you use `myblockstackapp://`.
+
+1. Open the `.xcworkspace` file in XCode if it isn't open already.
+2. Select the top node of your project.
+1. Select the **Info** tab in XCode.
+2. Scroll to **URL Types** and press **+** (plus) sign.
+3. Enter an **Identifier** and **URL Schemes** value.
+4. Set the **Role** to **Editor**.
+
+ When you are done the type appears as follows:
+
+ ![](images/url-type.png)
+
+### Add a splash screen
+
+All iOS applications require a splash page.
+
+1. Select `Assets.xcassets`
+2. Move your cursor into the area below Appicon.
+3. Right click and choose **New Image Set**
+
+ ![](images/image-set-0.png)
+
+4. Download the Blockstack icon.
+
+ ![](images/blockstack-icon.png)
+
+5. Drag the downloaded file into the **3X** position in your new Images folder.
+
+ ![](images/image-set-1.png)
+
+6. Select the `LaunchScreen.storyboard`.
+7. Choose **Open As > Source Code**.
+
+ ![](images/open-as.png)
+
+8. Replace the content of the `` element with the following:
+
+ ```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ```
+
+9. Immediately after scenes but before the close of the `` tag add the following ``.
+
+ ```xml
+
+
+
+
+ ```
+
+10. Choose **Run > Run app** in the emulator.
+
+ The emulator now contains a new splash screen.
+
+ ![](images/splash.png)
+
+
+### Update the Main.storyboard
+
+Rather than have you build up your own UI, this section has you copy and paste a layout into the XML file source code for the **Main.storyboard** file.
+
+1. Select the `Main.storyboard` file.
+2. Chooose **Open As > Source Code**
+
+ The `blockstack-example/blockstack-example/Base.lproj/Main.storyboard` file
+ defines the graphical elements. Some elements are required before you can
+ functionality to your code.
+
+3. Within the `` element, replace the existing `` subelement with the following:
+
+ ```xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ```
+
+### Add the UI variables to the ViewController file.
+
+In this section, you edit the `ViewController.swift` file using the storyboard as a starting point.
+
+1. Select the **Main.storyboard** and choose **Open As > Interface Builder - storyboard**.
+
+ ![](images/main-storyboard.png)
+
+2. With the interface builder open, display the `ViewController.swift` file in the rigth panel.
+
+ ![](images/view-editors.gif)
+
+4. In the storyboard, select the **Sign into Blockstack** button.
+
+5. Control-drag from the button to the code display in the editor on the right, stopping the drag at the line below controller's opening statement.
+
+ ![](images/add-action.gif)
+
+6. Repeat this process with the storyboard's purple **hello-blockstack-ios** label.
+
+ When you are done, your 'ViewController' file contains the following variables:
+
+ ```swift
+ class ViewController: UIViewController {
+
+ @IBOutlet var nameLabel: UILabel!
+ @IBOutlet var signInButton: UIButton!
+ ```
+
+ And XCode has added two outlines to the `Main.storyboard` source.
+
+ ```xml
+
+
+
+
+ ```
+
+ Your connectors will have their own `destination` and `id` values.
+
+
+### Edit the ViewController.swift file
+
+Now, you are ready to connect your application with your Blockstack Web
+Application. Normally, after building your Web application you would have
+registred it with Blockstack and the app would be available on the Web. This
+example skips this registration step and uses an example application we've
+already created for you:
+
+`https://heuristic-brown-7a88f8.netlify.com/redirect.html`
+
+This web application already has a redirect in place for you. You'll reference
+this application in your mobile add for now. In XCode, do the following;
+
+
+1. Open the `ViewController.swift` file.
+2. Add an import both for `Blockstack` and for `SafariServices`.
+
+ ```
+ import UIKit
+ import Blockstack
+ import SafariServices
+ ```
+
+3. Just before the `didReceiveMemoryWarning` function a private `updateUI()` function.
+
+ This function takes care of loading the user data from Blockstack.
+
+ ```swift
+ private func updateUI() {
+ DispatchQueue.main.async {
+ if Blockstack.shared.isSignedIn() {
+ // Read user profile data
+ let retrievedUserData = Blockstack.shared.loadUserData()
+ print(retrievedUserData?.profile?.name as Any)
+ let name = retrievedUserData?.profile?.name ?? "Nameless Person"
+ self.nameLabel?.text = "Hello, \(name)"
+ self.nameLabel?.isHidden = false
+ self.signInButton?.setTitle("Sign Out", for: .normal)
+ print("UI update SIGNED_IN")
+ } else {
+ self.nameLabel?.text = "hello-blockstack-ios"
+ self.signInButton?.setTitle("Sign into Blockstack", for: .normal)
+ print("UI update SIGNED_OUT")
+ }
+ }
+ }
+ ```
+
+ The function uses the `Blockstack.shared.isSignedIn()` method to determine if
+ the user is already logged into Blockstack or not. It then uses the
+ `Blockstack.shared.loadUserData()` method to load the user data and update
+ the application display with the username.
+
+5. Replace the content of the `viewDidLoad()` function so that it calls this private function.
+
+ ```swift
+ override func viewDidLoad() {
+ super.viewDidLoad()
+ // Do any additional setup after loading the view, typically from a nib.
+ self.updateUI()
+ }
+ ```
+
+9. Create a 'signIn()' function that handles both sign in and out.
+
+ The function uses the `Blockstack.shared.signIn()` and
+ `Blockstack.shared.signOut()` methods to sign the user into the application.
+
+ ```swift
+ @IBAction func signIn(_ sender: UIButton) {
+ if Blockstack.shared.isSignedIn() {
+ print("Currently signed in so signing out.")
+ Blockstack.shared.signOut()
+ self.updateUI()
+ } else {
+ print("Currently signed out so signing in.")
+ // Address of deployed example web app
+ Blockstack.shared.signIn(redirectURI: "https://heuristic-brown-7a88f8.netlify.com/redirect.html",
+ appDomain: URL(string: "https://heuristic-brown-7a88f8.netlify.com")!) { authResult in
+ switch authResult {
+ case .success(let userData):
+ print("Sign in SUCCESS", userData.profile?.name as Any)
+ self.updateUI()
+ case .cancelled:
+ print("Sign in CANCELLED")
+ case .failed(let error):
+ print("Sign in FAILED, error: ", error ?? "n/a")
+ }
+ }
+ }
+
+ }
+ ```
+
+## Troubleshooting your build in XCode
+
+XCode builds can retain old data. To ensure your builds are clean, try the following:
+
+1. Reset the simulator by choosing **Hardware -> Erase all content and settings** from the menu.
+2. In XCode, clean the project by choosing **Product > Clean** from the menu or press 'Command + Shift + K' on your keyboard.
+3. Clean the build folder by pressing 'Command + Option + Shift + K' on your keyboard.
+4. Run the code on the simulator again.
diff --git a/_layouts/externalurl.html b/_layouts/externalurl.html
index e8850381..a5acf476 100644
--- a/_layouts/externalurl.html
+++ b/_layouts/externalurl.html
@@ -1,2 +1,2 @@
{{page.title}}
-
+
diff --git a/_org/whitepaper-token.md b/_org/whitepaper-token.md
index d08e3b78..9649d6ff 100644
--- a/_org/whitepaper-token.md
+++ b/_org/whitepaper-token.md
@@ -2,5 +2,5 @@
title: Blockstack Token Sale Mechanics
layout: externalurl
permalink: /:collection/:path.html
-redirect: https://blockstack.com/tokenpaper.pdf
+redirect_url: https://blockstack.com/tokenpaper.pdf
---
diff --git a/_org/whitepaper-tokensale.md b/_org/whitepaper-tokensale.md
index 2ca55c20..972014cb 100644
--- a/_org/whitepaper-tokensale.md
+++ b/_org/whitepaper-tokensale.md
@@ -2,5 +2,5 @@
title: Blockstack Token Whitepaper
layout: externalurl
permalink: /:collection/:path.html
-redirect: https://blockstack.com/distribution.pdf
+redirect_url: https://blockstack.com/distribution.pdf
---
diff --git a/_site/2017/05/25/post63.html b/_site/2017/05/25/post63.html
index 4d645cbc..aef50ded 100644
--- a/_site/2017/05/25/post63.html
+++ b/_site/2017/05/25/post63.html
@@ -5,8 +5,8 @@
+ Site tags
-Site tags | Blockstack
diff --git a/_site/404.html b/_site/404.html
index 22b6274c..a091c4a4 100644
--- a/_site/404.html
+++ b/_site/404.html
@@ -5,8 +5,8 @@
+ Feeling Lost
-Feeling Lost | Blockstack
diff --git a/_site/android/tutorial.html b/_site/android/tutorial.html
index 4b09e3af..e17e0c57 100644
--- a/_site/android/tutorial.html
+++ b/_site/android/tutorial.html
@@ -5,8 +5,8 @@
+ Android SDK Tutorial (Pre-release)
-Android SDK Tutorial (Pre-release) | Blockstack
@@ -17,9 +17,9 @@
-
+
+{"datePublished":"2018-11-05T14:56:16-08:00","url":"https://docs.blockstack.org/android/tutorial.html","dateModified":"2018-11-05T14:56:16-08:00","mainEntityOfPage":{"@type":"WebPage","@id":"https://docs.blockstack.org/android/tutorial.html"},"author":{"@type":"Person","name":"Blockstack"},"description":"Android SDK Tutorial (Pre-release)","@type":"BlogPosting","headline":"Android SDK Tutorial (Pre-release)","@context":"http://schema.org"}
@@ -241,9 +241,9 @@
-
@@ -654,16 +654,8 @@ iniatial state by creating an emulator to run it in. Open Android Studio and do
Now that you have created your initial project and verified it running in an emulator, you are ready to begin configuring the application for use with Blockstack.
-
In studio, open the AndroidManifest.xml file.
-
Add the a launchMode to the .MainActivity definition.
Blockstack requires that the activity that starts the sign-in process also
-handles the auth reponse token. This means that the activity needs to run in
-singleTask launch mode.
+
In studio, open the AndroidManifest.xml file.
Add an <intent-filter> with the custom handler for Blockstack.
@@ -718,12 +710,13 @@ handles the auth reponse token. This means that the activity needs to run in
The new interface includes a BlockstackSignInButton which is provided by
the SDK. This SDK includes a themed “Sign in with Blockstack” button
-(BlockstackSignInButton). You use this button in your here with the
+(BlockstackSignInButton). You use this button here with the
org.blockstack.android.sdk.ui.BlockstackSignInButton class.
<?xml version="1.0" encoding="utf-8"?>
@@ -789,7 +782,7 @@ the SDK. This SDK includes a themed “Sign in with Blockstack” button
tools:layout_editor_absoluteX="6dp"
tools:layout_editor_absoluteY="70dp" />
- </android
+ </android>
This codes adds a button and some text to your application.
@@ -815,17 +808,15 @@ the SDK. This SDK includes a themed “Sign in with Blockstack” button
When you are done, your imports should appear as follows:
@@ -849,36 +839,19 @@ the SDK. This SDK includes a themed “Sign in with Blockstack” button
overridefunonCreate(savedInstanceState:Bundle?){super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)
-
- signInButton.isEnabled=false
-
- valappDomain=URI("https://flamboyant-darwin-d11c17.netlify.com")
- valredirectURI=URI("${appDomain}/redirect")
- valmanifestURI=URI("${appDomain}/manifest.json")
+
valscopes=arrayOf(Scope.StoreWrite)
+ valconfig="https://flamboyant-darwin-d11c17.netlify.com"
+ .toBlockstackConfig(scopes)
- valconfig=java.net.URI("https://flamboyant-darwin-d11c17.netlify.com").run{
- org.blockstack.android.sdk.BlockstackConfig(
- this,
- redirectURI,
- manifestURI,
- scopes
- }
-
- _blockstackSession=BlockstackSession(this,config,
- onLoadedCallback={
- signInButton.isEnabled=true
- })
-
+ _blockstackSession=BlockstackSession(this,config)
+
+ signInButton.isEnabled=truesignInButton.setOnClickListener{view:View->
- blockstackSession().redirectUserToSignIn{userData->
- if(userData.hasValue){
- runOnUiThread{
- onSignIn(userData.value!!)
- }
- }
- }
+ blockstackSession().redirectUserToSignIn{
+ // only called on error
+}}if(intent?.action==Intent.ACTION_VIEW){// handle the redirect from sign in
@@ -891,14 +864,14 @@ the SDK. This SDK includes a themed “Sign in with Blockstack” button
Define the initial state for the signInButton.
-
Supply authentication information for connecting to your Blockstack app: appDomain, redirectURI, manifestURI and scopes
+
Supply authentication information for connecting to your Blockstack app: appDomain and scopes (for redirectURI, manifestURI the default values are used)
Add a listener for the button click.
Notice that the application in this example is a URI you have not set up.
Registering and application name takes time, so in time’s interest you’ll
use an existing app that is identical to the hello-world you created
- earlier. For a produciton verison, you’ll need to replace appDomain,
+ earlier. For a production version, you’ll need to replace appDomain,
redirectURI, manifestURI and scopes with values appropriate for your
app.
@@ -907,9 +880,7 @@ the SDK. This SDK includes a themed “Sign in with Blockstack” button
privatefunonSignIn(userData:UserData){userDataTextView.text="Signed in as ${userData.decentralizedID}"
-
signInButton.isEnabled=false
-
}
@@ -972,31 +943,23 @@ the SDK. This SDK includes a themed “Sign in with Blockstack” button
privatevar_blockstackSession:BlockstackSession?=null
-
overridefunonCreate(savedInstanceState:Bundle?){super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)signInButton.isEnabled=false
- valappDomain=URI("https://flamboyant-darwin-d11c17.netlify.com")
- valredirectURI=URI("${appDomain}/redirect")
- valmanifestURI=URI("${appDomain}/manifest.json")valscopes=arrayOf(Scope.StoreWrite)
+ valconfig="https://flamboyant-darwin-d11c17.netlify.com"
+ .toBlockstackConfig(scopes)
- _blockstackSession=BlockstackSession(this,appDomain,redirectURI,manifestURI,scopes,
- onLoadedCallback={signInButton.isEnabled=true
- })
-
+ _blockstackSession=BlockstackSession(this,config)
+ signInButton.isEnabled=truesignInButton.setOnClickListener{view:View->
- blockstackSession().redirectUserToSignIn{userData->
- if(userData.hasValue){
- runOnUiThread{
- onSignIn(userData)
- }
- }
- }
+ blockstackSession().redirectUserToSignIn{
+ // only called on error
+}}if(intent?.action==Intent.ACTION_VIEW){handleAuthResponse(intent)
@@ -1007,7 +970,6 @@ the SDK. This SDK includes a themed “Sign in with Blockstack” button
userDataTextView.text="Signed in as ${userData.decentralizedID}"signInButton.isEnabled=false
-
}overridefunonNewIntent(intent:Intent?){
@@ -1046,8 +1008,6 @@ the SDK. This SDK includes a themed “Sign in with Blockstack” button
throwIllegalStateException("No session.")}}
-
-
}
Note: This tutorial was written on macOS High Sierra 10.13.4. If you use a Windows or Linux system, you can still follow along. However, you will need to "translate" appropriately for your operating system. Additionally, this tutorial assumes you are accessing the Blockstack Browser web application via Chrome. The application you build will also work with a local installation and/or with browsers other than Chrome.
+
About this tutorial and the prerequisites you need
-
At minimum, Blockstack requires macOS High Sierra. This tutorial was written for
-a user running macOS High Sierra 10.13.4. The application you build is a
-React.js application that is completely decentralized and server-less. While
-not strictly required to follow along, basic familiarity with React.js is
-helpful.
+
The storage application you build with this tutorial is a React.js application
+that is completely decentralized and server-less. While not strictly required
+to follow along, basic familiarity with React.js is helpful.
When complete, the app is capable of the following:
diff --git a/_site/browser/browser-introduction.html b/_site/browser/browser-introduction.html
index 47283ab2..9d84902d 100644
--- a/_site/browser/browser-introduction.html
+++ b/_site/browser/browser-introduction.html
@@ -5,21 +5,21 @@
+ Introduction to the Blockstack Browser
-Get the Blockstack Browser | Blockstack
-
+
-
-
+
+
-
+
+{"datePublished":"2018-11-05T14:56:16-08:00","url":"https://docs.blockstack.org/browser/browser-introduction.html","dateModified":"2018-11-05T14:56:16-08:00","mainEntityOfPage":{"@type":"WebPage","@id":"https://docs.blockstack.org/browser/browser-introduction.html"},"author":{"@type":"Person","name":"Blockstack"},"description":"Introduction to the Blockstack Browser","@type":"BlogPosting","headline":"Introduction to the Blockstack Browser","@context":"http://schema.org"}
@@ -118,22 +118,53 @@
+
@@ -166,9 +197,9 @@
-
+
- Oct 31, 2018
+ Nov 5, 2018
@@ -176,33 +207,21 @@
The Blockstack Browser gives users the ability to explore and use the
-decentralized applications (dapps). The decentralized applications are a new way
-to interact with the internet. Dapps give users control of their data. Data
-about them personally, name, birthdate, phone number and data about what they do
-such as visiting a website or buying an item.
+decentralized applications (Dapps). Dapps are a new way to interact with the
+internet. Dapps give users control of their data. Data about them personally,
+name, birthdate, phone number and data about what they do such as visiting a
+website or buying an item.
Through the Blockstack browser application you can create an identity. An identity
-represents you as you interact with others through Dapps. The Blockstack
+represents you as you interact with others through Dapps. The Blockstack
Browser is itself, a simple Dapp. It allows you to:
@@ -219,9 +238,11 @@ client application on your computer.
If all you want to do is create, manage, and fund an identity and then interact
with Dapps, you can simply use the web edition. If you have concerns about net
-censorship, hightened security concerns, or develop a Dapp yourself, you may
+censorship, heightened security concerns, or want to develop a Dapp yourself, you may
want to download and install the browser’s client edition.
+
To use the web application to create an identity,
+
Using the Browser on public computers
Before you use the web application, it is important to note that once you log
@@ -234,166 +255,7 @@ closing the tab or even rebooting the computer does not log you out. Instead,
you should be sure to choose Settings > RESET BROWSER before leaving the web
application.
Remember, for most users the Blockstack Browser web application should
-suffice. You only need to install the client if you have additional, advanced
-concerns about Internet or identity. Though not required, some Dapp developrs
-may find it useful to install the client edition.
-
-
The Blockstack Browser installer is a multiple-context installer. If you
-run it as a user, the installation is avalable only for that user. If you
-install as administrator, the installation installs for all users. To find an
-installer for your operating system, visit the browser installation page.
-
-
On Mac
-
-
Installation requires that you have macOS High Sierra 10.12 or higher. Do the following to install:
Double-click the downloaded DMG file to launch the installer.
-
-
-
-
Drag the Blockstack.app to the Applications folder.
-
-
Double-click the Blockstack.app to launch it.
-
-
The system displays a notice about opening the file:
-
-
-
-
-
Choose Open.
-
-
The system opens your default browser with the Blockstack Browser
-application, running from your machine (localhost). You’ll also see the
-Blockstack icon in your machine’s
-
-
-
-
If you have loaded an identity already via the Blockstack web application,
-you are already logged into the local application:
-
-
-
-
-
-
On Windows
-
-
Installation requires that you have Windows 10 or higher. Do the following to
-install:
Note: The Blockstack script used in this procedure runs docker commands. Depending on how you installed and configure Dockered on your system, it may or may not be necessary to have root or sudo privileges. For this reason, the commands below show the use of sudo when interacting with the script or the docker executable. If your installation allows running Docker with lower privileges, you can omit it.
The system launches the Blockstack Browser application for you.
-
-
-
-
-
-
Until you stop the Blockstack containers, the application will continue to run
-on your system. To display the status of the Blockstack containers, you can use
-the docker container ls command.
Locate the Blockstack Browser and choose Uninstall.
-
-
-
-
-
-
On Linux
-
-
Your Blockstack instalaltion relies on Docker containers and their associated
-images. It also includes a supporting protocol handler you must remove. If you
-installed Docker so that you can run Blockstack, you can uninstall Docker as well,
-but that is not explained here.
-
-
Do the following to uninstall Blockstack:
-
-
-
-
Stop and remove the Docker containers if they are running.
@@ -269,6 +269,8 @@ decentralized, server-less application. You work through the following sections:
+
Note: This tutorial was written on macOS High Sierra 10.13.4. If you use a Windows or Linux system, you can still follow along. However, you will need to "translate" appropriately for your operating system. Additionally, this tutorial assumes you are accessing the Blockstack Browser web application via Chrome. The application you build will also work with a local installation and/or with browsers other than Chrome.
+
About this tutorial and the prerequisites you need
For this tutorial, we will use the following tools:
@@ -279,11 +281,9 @@ decentralized, server-less application. You work through the following sections:
blockstack.js to authenticate the user and work with the user’s identity/profile information
-
At minimum, Blockstack requires macOS High Sierra. This tutorial was written for
-a user running macOS High Sierra 10.13.4. The application you build is a
-React.js application that is completely decentralized and server-less. While
-not strictly required to follow along, basic familiarity with React.js is
-helpful.
+
The application you build is a React.js application that is completely
+decentralized and server-less. While not strictly required to follow along,
+basic familiarity with React.js is helpful.
When complete, the app is capable of the following:
diff --git a/_site/browser/ids-creating.html b/_site/browser/ids-creating.html
index b4d1bf5b..3f9da4c9 100644
--- a/_site/browser/ids-creating.html
+++ b/_site/browser/ids-creating.html
@@ -5,8 +5,8 @@
+ Working with IDS
-Working with IDS | Blockstack
@@ -17,9 +17,9 @@
-
+
+{"datePublished":"2018-11-05T14:56:16-08:00","url":"https://docs.blockstack.org/browser/ids-creating.html","dateModified":"2018-11-05T14:56:16-08:00","mainEntityOfPage":{"@type":"WebPage","@id":"https://docs.blockstack.org/browser/ids-creating.html"},"author":{"@type":"Person","name":"Blockstack"},"description":"Working with IDS","@type":"BlogPosting","headline":"Working with IDS","@context":"http://schema.org"}
@@ -118,22 +118,53 @@
+
@@ -166,9 +197,9 @@
-
+
- Oct 31, 2018
+ Nov 5, 2018
diff --git a/_site/browser/ids-introduction.html b/_site/browser/ids-introduction.html
index 021ce872..2cfb6ad0 100644
--- a/_site/browser/ids-introduction.html
+++ b/_site/browser/ids-introduction.html
@@ -5,8 +5,8 @@
+ Get and use a Blockstack ID
-Get and use a Blockstack ID | Blockstack
@@ -17,9 +17,9 @@
-
+
+{"datePublished":"2018-11-05T14:56:16-08:00","url":"https://docs.blockstack.org/browser/ids-introduction.html","dateModified":"2018-11-05T14:56:16-08:00","mainEntityOfPage":{"@type":"WebPage","@id":"https://docs.blockstack.org/browser/ids-introduction.html"},"author":{"@type":"Person","name":"Blockstack"},"description":"Get and use a Blockstack ID","@type":"BlogPosting","headline":"Get and use a Blockstack ID","@context":"http://schema.org"}
@@ -118,22 +118,53 @@
+
If all you want to do is create, manage, and fund an identity and then interact
+with Dapps, you should use the web edition. If you
+have concerns about net censorship, heightened security concerns, or want to
+develop a Dapp yourself, you may want to download and install the browser’s
+client edition; though it is not required. This page explains how to install or
+uninstall the browser client on a workstation.
Remember, for most users the Blockstack Browser web application should
+suffice. You only need to install the client if you have additional, advanced
+concerns about Internet or identity. Though not required, some Dapp developrs
+may find it useful to install the client edition.
+
+
The Blockstack Browser installer is a multiple-context installer. If you
+run it as a user, the installation is avalable only for that user. If you
+install as administrator, the installation installs for all users. To find an
+installer for your operating system, visit the browser installation page.
+
+
On Mac
+
+
Installation requires that you have macOS High Sierra 10.12 or higher. Do the following to install:
Double-click the downloaded DMG file to launch the installer.
+
+
+
+
Drag the Blockstack.app to the Applications folder.
+
+
Double-click the Blockstack.app to launch it.
+
+
The system displays a notice about opening the file:
+
+
+
+
+
Choose Open.
+
+
The system opens your default browser with the Blockstack Browser
+application, running from your machine (localhost). You’ll also see the
+Blockstack icon in your machine’s
+
+
+
+
If you have loaded an identity already via the Blockstack web application,
+you are already logged into the local application:
+
+
+
+
+
+
On Windows
+
+
Installation requires that you have Windows 10 or higher. Do the following to
+install:
Note: The Blockstack script used in this procedure runs docker commands. Depending on how you installed and configure Dockered on your system, it may or may not be necessary to have root or sudo privileges. For this reason, the commands below show the use of sudo when interacting with the script or the docker executable. If your installation allows running Docker with lower privileges, you can omit it.
The system launches the Blockstack Browser application for you.
+
+
+
+
+
+
Until you stop the Blockstack containers, the application will continue to run
+on your system. To display the status of the Blockstack containers, you can use
+the docker container ls command.
Locate the Blockstack Browser and choose Uninstall.
+
+
+
+
+
+
On Linux
+
+
Your Blockstack instalaltion relies on Docker containers and their associated
+images. It also includes a supporting protocol handler you must remove. If you
+installed Docker so that you can run Blockstack, you can uninstall Docker as well,
+but that is not explained here.
+
+
Do the following to uninstall Blockstack:
+
+
+
+
Stop and remove the Docker containers if they are running.
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/_site/browser/multi-player-storage.html b/_site/browser/multi-player-storage.html
index 53337f5e..0e1729ce 100644
--- a/_site/browser/multi-player-storage.html
+++ b/_site/browser/multi-player-storage.html
@@ -5,8 +5,8 @@
+ Manage Data with Gaia
-Manage Data with Gaia | Blockstack
@@ -17,9 +17,9 @@
-
+
+{"datePublished":"2018-11-05T14:56:16-08:00","url":"https://docs.blockstack.org/browser/multi-player-storage.html","dateModified":"2018-11-05T14:56:16-08:00","mainEntityOfPage":{"@type":"WebPage","@id":"https://docs.blockstack.org/browser/multi-player-storage.html"},"author":{"@type":"Person","name":"Blockstack"},"description":"Manage Data with Gaia","@type":"BlogPosting","headline":"Manage Data with Gaia","@context":"http://schema.org"}
@@ -241,9 +241,9 @@
-
+
- Oct 31, 2018
+ Nov 5, 2018
@@ -280,11 +280,13 @@ topics:
About this tutorial and the prerequisites you need
-
At minimum, Blockstack requires macOS High Sierra. This tutorial was written for
-a user running macOS High Sierra 10.13.4. The application you build is a
-React.js application that is completely decentralized and server-less. While
-not strictly required to follow along, basic familiarity with React.js is
-helpful.
+
Note: This tutorial was written for a user running macOS. If you are running a Windows
+machine, you can still work through this tutorial. You will need to adjust the
+instructions for your environment.
+
+
The application you build is a React.js application that is completely
+decentralized and server-less. While not strictly required to follow along,
+basic familiarity with React.js is helpful.
When complete, the app is capable of the following:
@@ -310,6 +312,8 @@ it. Finally, if you get stuck at any point
while working on the tutorial, the completed source code is available for
you to check your work against.
+
High Sierra 10.13.4.
+
Use npm to install Yeoman and the Blockstack App Generator
You use npm to install Yeoman. Yeoman is a generic scaffolding system that
diff --git a/_site/browser/purchase-id.html b/_site/browser/purchase-id.html
index f16c0f54..49ae594e 100644
--- a/_site/browser/purchase-id.html
+++ b/_site/browser/purchase-id.html
@@ -5,8 +5,8 @@
+
Purchase your own domain ID
-Purchase your own domain ID | Blockstack
@@ -17,9 +17,9 @@
-
+
+{"datePublished":"2018-11-05T14:56:16-08:00","url":"https://docs.blockstack.org/browser/purchase-id.html","dateModified":"2018-11-05T14:56:16-08:00","mainEntityOfPage":{"@type":"WebPage","@id":"https://docs.blockstack.org/browser/purchase-id.html"},"author":{"@type":"Person","name":"Blockstack"},"description":"Purchase your own domain ID","@type":"BlogPosting","headline":"Purchase your own domain ID","@context":"http://schema.org"}
@@ -118,22 +118,53 @@
+
An incentive mechanism for application developers in the early stage (first four years) of the ecosystem and helps with bootstrapping the two-sided market.
+
+
+
+
App Mining
+
A system where the Blockstack community funds decentralized app teams.
+
+
+
+
Atlas
+
A peer network provide a global index for discovery
+
+
+
+
block
+
A discrete group of records written to a blockchain that can effectively be identified and referenced by the
+use of headers that contain a digital fingerprint of the records each block contains.
+
+
+
+
blockchain
+
A database created and shared by the members of a peer-to-peer computer network which each member of that network can independently trust due to the rules governing the database’s creation. A blockchain can therefore be used to replace centralized databases.
+
+
+
+
Blockchain Name System (BNS)
+
Replacement for DNS.
+
+
+
+
blockstack browser
+
An application for accessing identity and storage.
+
+
+
+
Blockstack Core
+
A complete version of our open-source software available on Github at https://github.com/blockstack/blockstack-core/ that governs the creation of the blockchain, the smart contracts that may be written to our blockchain, and other systems that make up the Blockstack network, when run on the systems and devices of our users and developers.
+
+
+
+
blockstack id
+
See id.blockstack
+
+
+
+
Burning
+
Burning a token means that the token is transferred to an address that is a black hole—one that is not owned by any entity and for which guessing the applicable private key is effectively impossible based on known mathematical principles. This effectively destroys the token by making it unavailable for future use and decreases the total number of tokens available from that point forward.
+
+
+
+
consensus hash
+
A consensus hash is a cryptographic hash that each node calculates at each block. It is derived from the accepted state transitions in the last-processed block, and a geometric series of prior-calculated consensus hashes.
+
+
+
+
+
Consensus rules
+
The rules governing the creation of new valid records in a blockchain database, and the mining algorithms used for this purpose.
+
+
+
+
control plane
+
The part of a network that carries signaling traffic and is responsible for routing. Control packets originate from or are destined for a router. Functions of the control plane include system configuration and management.
+
+
+
+
core node
+
A server that runs Blockstack Core services.
+
+
+
+
crypto-asset
+
A digital asset which utilises cryptography, peer-to-peer networking, and a public ledger to regulate the creation of new units, verify transactions, and secure the transactions without the intervention of any middleman.
+
+
+
+
cryptography
+
The practise and study of encryption and decryption - encoding data so that it can only be decoded by specific individuals. A system for encrypting and decrypting data is a cryptosystem.
+
+
+
+
decentralized application (Dapp)
+
A Dapp is a service that enables direct interaction between end users and providers (e.g. connecting buyers and sellers in some marketplace, owners and stores in file storage). A term coined by Ethereum. See their glossary: http://ethdocs.org/en/latest/glossary.html
+
+
+
+
digital asset
+
Also referred to as a crypto-asset. Any set of unique digital information—including, for example, programs, decentralized programs, isolated chunks of programming code, collections of data, e-mail or web addresses or cryptocurrency tokens—that is capable of being stored and uniquely tracked on a computer network such as the Blockstack network and over which a user can maintain control through that network.
+
+
+
+
digital fingerprint
+
A digital fingerprint is a unique number of a fixed length that can be produced by running any set of digital information through something called a cryptographic hash function. Each set of digital information (including a digital asset, and the digital record of any network operation on that digital asset) should (as a practical matter) have a unique digital fingerprint, which allows that set of digital information to be identified. However, it is almost impossible to recreate a digital asset from its digital fingerprint. The Blockstack network uses industry-standard algorithms such as SHA-256 to create digital fingerprints.
+
+
+
+
digital signature
+
A digital signature is a sequence of digital information combining a user’s private key and any digital information that the user wishes to sign. Any other party can use the user’s paired public key to verify that the digital signature is authentic, i.e. that the public key was generated from a particular piece of digital information and the user’s private key.
+
+
+
+
distributed hash tables (DHT)
+
A form of network used to store some content in the form of key/value pairs. ... This experimental project try to avoid keeping all the blockchain, but instead prefers to store it in a DHT.
+
+
+
+
ephemeral key
+
A cryptographic key is called ephemeral if it is generated for each execution of a key establishment process.
+
+
+
+
fork
+
The term fork is used to refer both to any situation where there are two or more competing versions of a blockchain on a network (a situation that may arise and resolve itself in the ordinary course of network operations due to lags in communication between core nodes) and any software update that is proposed for adoption by the core nodes of a blockchain network that may result in a persistent fork on the network, with core nodes that adopt the update recognizing one version of the blockchain and those which do not recognizing another.
+
+
+
+
Gaia
+
Decentralized storage
+
+
+
+
genesis block
+
The genesis block is the first block of the Stacks blockchain, which will create the initial 1.32 billion Stacks Tokens.
+
+
+
+
id.blockstack
+
An identifier in the Blockstack, for example moxiegirl.id.blockstack. This is your name & identity that is registered in the .id namespace on Blockstack. Your personal data and storage are built around this ID. Apps that want to access your data use your permission and identity to find it. An id is usually a shorthand for a longer, hash ID string, for example ID-1Fj9kkw15P51Fj9kkw15P5xJmyefWhLKrQMKNPREfaqsJ
+
+
+
+
+
identity management (IDM)
+
Identity management, also known as identity and access management is, in computer security, the security and business discipline that enables the right individuals to access the right resources at the right times and for the right reason
+
+
+
+
know your customer (KYC)
+
Or KYC, is a popular term used in the banking or financial field. KYC is a process where financial institutions, insurers and other companies obtain information about the identity and address of the customers as part of risk management.
+
+
+
+
KYC
+
See know your customer
+
+
+
+
light clients
+
Clients that can independently validate the existence of transactions by downloading only block headers and not the entire blockchain.
+
+
+
+
mesh network
+
A local network topology in which the infrastructure nodes (i.e. bridges, switches, and other infrastructure devices) connect directly, dynamically and non-hierarchically to as many other nodes as possible and cooperate with one another to efficiently route data from/to clients.
+
+
+
+
mining
+
Mining generally refers to the process of performing certain functions for a network such as adding new records to a blockchain in exchange for mining rewards; it may also refer to other mechanisms whereby rewards (usually in the form of cryptocurrency) are provided for performing other tasks helpful to the network.
+
+
+
+
mining power
+
A miner’s (or group of miners’) mining power is equal to the probability it will be selected to write a new block to the blockchain. Depending on the mechanism for mining, this is usually related to the overall share of computing power or cryptoassets the miner or miners possess relative to all miners for that blockchain.
+
+
+
+
mining rewards
+
Mining rewards are newly issued tokens received by miners in exchange for adding new records to the blockchain or other activities beneficial to the network.
+
+
+
+
name
+
An identifier or name. Names are a type of digital asset in the Blockstack network. If you have signed into the Blockstack Browser, you created a name. If an application developer registered an application within Blockstack, then they registered a name.
+
+
+
+
network operation
+
A network operation is any change to the information about a digital asset (or smart contract) stored on a blockchain, including, for example, a change in the digital asset’s owner, or a change in the location at which it is stored on the network. How and when these network operations are performed for each digital asset is governed, on the Blockstack network, either by the Blockstack Core software or a smart contract.
+
+
+
+
Public Key Infrastructure (PKI)
+
A system which returns a cryptographic public key associated with a name.
+
+
+
+
private key
+
A private key is a very large random sequence of digital information (effectively a very long password) that should be known only by a single user of the network and cannot be plausibly guessed by a third party in a reasonable amount of time. A user generates this large random sequence locally on a computer and should never share it with anyone. Each private key has a paired sequence of digital information, called a public key, which a user can share publicly.
+
+
+
+
proof-of-burn mining
+
The consensus algorithm used in the Stacks blockchain where miners destroy a proof-of-work-based cryptocurrency (currently Bitcoin) to get tokens; this enables the functionality where nodes can select between conflicting blockchain forks, as the blockchain fork with the most amount of cryptocurrency burned is considered to be the correct fork.
+
+
+
+
proof-of-work
+
A proof-of-work system or proof-of-work mining is a mining mechanism where miners must expend computing power to solve complicated cryptographic puzzles, and prove that they have done so by writing the solution to the blockchain, in order to be allowed to add blocks to a blockchain. This is the mining system used, for example, by Bitcoin.
+
+
+
+
replicated state machines (RSMs)
+
This is a model for reasoning about distributed computer programs -- any program (plus it's input) can be represented as a state machine, and when trying to get a distributed set of servers to agree on the output of an algorithm, you can model that process as N different state machines
+
+
+
+
smart contract
+
A smart contract is a computer program written to a blockchain such as the Blockstack blockchain by developers. This computer program defines the various network operations that can be performed on the digital assets on the blockchain, the computations that can be performed using the smart contract, along with defining various important properties of the respective digital assets like ownership rights and the cost in fuel required to register the digital assets.
+
+
+
+
soft fork
+
A soft fork is a proposed update to the software governing the network that results in a post-update network that is compatible with the network as it existed prior to the update, because it restricts the network operations that can be performed after the update.
+
+
+
+
Stacks blockchain
+
The Stacks blockchain is the custom blockchain being developed for use by the Blockstack network that will use the Stacks token as its native currency and which will include the genesis block and subsequent blocks created by the mining activities described in The Blockstack Network—Development of the Blockstack network.
+
+
+
+
transaction
+
A transaction is a unit of work within a block.
+
+
+
+
transaction fee
+
Fees paid by participants in a transaction to miners.
+
+
+
+
two-sided market problem
+
Economic platforms having two distinct user groups that provide each other with network benefits. The Blockstack platform is a classic two-sided market.
+
+
+
+
username
+
A shorthand name for your your id.blockstack.
+
+
+
+
virtual blockchain
+
A layer that sits on top of a blockchain that introduces new functionality and operations without requiring changes to the underlying blockchain
+
+
+
+
wallet address
+
A wallet address is the form in which a public key can be presented and recorded on a blockchain. Wallet addresses are therefore used to assign the ownership of digital assets on the Blockstack network.
+
+
+
+
Web of trust mining
+
Web-of-trust mining provides incentive mechanisms for users where an initial trusted-set of unique users is curated in the genesis block and, in the future, the initial set of users can expand the web-of-trust after the network goes live.
+
+
+
+
Zone file
+
A Domain Name System (DNS) zone file is a text filethat describes a DNS zone. A DNS zone is a subset, often a single domain, of the hierarchical domain name structure of the DNS.
Note: This tutorial was written on macOS High Sierra 10.13.4. If you use a Windows or Linux system, you can still follow along. However, you will need to "translate" appropriately for your operating system. Additionally, this tutorial assumes you are accessing the Blockstack Browser web application via Chrome. The application you build will also work with a local installation and/or with browsers other than Chrome.