<pclass="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.</p>
<p>Each Bitcoin transaction for Blockstack contains signatures from two sets of keys: the name owner, and the payer. The owner <codeclass="highlighter-rouge">scriptSig</code> and <codeclass="highlighter-rouge">scriptPubKey</code> fields are generated from the key(s) that own the given name. The payer <codeclass="highlighter-rouge">scriptSig</code> and <codeclass="highlighter-rouge">scriptPubKey</code> fields are used to <em>subsidize</em> 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.</p>
<p>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.</p>
<p>The general transaction layout is as follows:</p>
<p>(1) The owner <codeclass="highlighter-rouge">scriptSig</code> is <em>always</em> the first input.
(2) The <codeclass="highlighter-rouge">OP_RETURN</code> script that describes the name operation is <em>always</em> the first output.
(3) The owner <codeclass="highlighter-rouge">scriptPubKey</code> is <em>always</em> 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” <codeclass="highlighter-rouge">scriptPubKey</code> for the payer.
Different operations require different outputs.</p>
<h2id="payload-format">Payload Format</h2>
<p>Each Blockstack transaction in Bitcoin describes the name operation within an <codeclass="highlighter-rouge">OP_RETURN</code> output. It encodes name ownership, name fees, and payments as <codeclass="highlighter-rouge">scriptPubKey</code> outputs. The specific operations are described below.</p>
<p>Each <codeclass="highlighter-rouge">OP_RETURN</code> payload <em>always</em> starts with the two-byte string <codeclass="highlighter-rouge">id</code> (called the “magic” bytes in this document), followed by a one-byte <codeclass="highlighter-rouge">op</code> that describes the operation.</p>
<li>Payment <codeclass="highlighter-rouge">scriptPubkey</code> script for change</li>
<li><codeclass="highlighter-rouge">p2pkh</code><codeclass="highlighter-rouge">scriptPubkey</code> to the burn address (0x00000000000000000000000000000000000000)</li>
</ul>
<p>Notes:</p>
<ul>
<li><codeclass="highlighter-rouge">register_addr</code> is a base58check-encoded <codeclass="highlighter-rouge">ripemd160(sha256(pubkey))</code> (i.e. an address). This address <strong>must not</strong> have been used before in the underlying blockchain.</li>
<li><codeclass="highlighter-rouge">script_pubkey</code> is either a <codeclass="highlighter-rouge">p2pkh</code> or <codeclass="highlighter-rouge">p2sh</code> compiled Bitcoin script for the payer’s address.</li>
<li><codeclass="highlighter-rouge">scriptPubkey</code> 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).</li>
<li><codeclass="highlighter-rouge">scriptPubkey</code> for the payer’s change</li>
<li><codeclass="highlighter-rouge">scriptPubkey</code> for the burn address (to pay the name cost)</li>
</ul>
<p>Notes:</p>
<ul>
<li>This transaction is identical to a <codeclass="highlighter-rouge">NAME_REGISTRATION</code>, except for the presence of the fourth output that pays for the name cost (to the burn address).</li>
<li>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).</li>
<li>Both variations are supported. Variation 1 was designed for the time when
Bitcoin only supported 40-byte <codeclass="highlighter-rouge">OP_RETURN</code> outputs.</li>
<li>This operation can be used to transfer a name to a new address by setting the
second output (the first <codeclass="highlighter-rouge">scriptPubkey</code>) to be the <codeclass="highlighter-rouge">scriptPubkey</code> of the new
<p>Description: This transaction sets the name state for a name to the given
<codeclass="highlighter-rouge">value</code>. In practice, this is used to announce new DNS zone file hashes to the <ahref="/core/atlas/overview.html">Atlas
magic op hash128(name.ns_id,consensus hash) zone file hash
</code></pre>
</div>
<p>Note that <codeclass="highlighter-rouge">hash128(name.ns_id, consensus hash)</code> 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 <ahref="#method-glossary">Method Glossary</a> below.</p>
<li>The <codeclass="highlighter-rouge">keep data?</code> byte controls whether or not the name’s 20-byte value is preserved. This value is either <codeclass="highlighter-rouge">></code> to preserve it, or <codeclass="highlighter-rouge">~</code> to delete it.</li>
<li><codeclass="highlighter-rouge">p2pkh</code> script to the burn address <codeclass="highlighter-rouge">1111111111111111111114oLvT2</code>, whose public key hash is 0x00000000000000000000000000000000</li>
</ul>
<p>Notes:</p>
<ul>
<li>The <codeclass="highlighter-rouge">reveal_addr</code> field is the address of the namespace revealer public key. The revealer private key will be used to generate <codeclass="highlighter-rouge">NAME_IMPORT</code> transactions.</li>
<li>This transaction must be sent within 1 day of the <codeclass="highlighter-rouge">NAMESPACE_PREORDER</code></li>
<li>The second output (with the namespace revealer) <strong>must</strong> be a <codeclass="highlighter-rouge">p2pkh</code> script</li>
<li>The address of the second output <strong>must</strong> be the <codeclass="highlighter-rouge">reveal_addr</code> in the <codeclass="highlighter-rouge">NAMESPACE_PREORDER</code></li>
</ul>
<p>Pricing:</p>
<p>The rules for a namespace are as follows:</p>
<ul>
<li>a name can fall into one of 16 buckets, measured by length. Bucket 16 incorporates all names at least 16 characters long.</li>
<li>the pricing structure applies a multiplicative penalty for having numeric characters, or punctuation characters.</li>
<li>the price of a name in a bucket is ((coeff) * (base) ^ (bucket exponent)) / ((numeric discount multiplier) * (punctuation discount multiplier))</li>
</ul>
<p>Example:</p>
<ul>
<li>base = 10</li>
<li>coeff = 2</li>
<li>nonalpha discount: 10</li>
<li>no-vowel discount: 10</li>
<li>buckets 1, 2: 9</li>
<li>buckets 3, 4, 5, 6: 8</li>
<li>buckets 7, 8, 9, 10, 11, 12, 13, 14: 7</li>
<li>buckets 15, 16+:</li>
</ul>
<p>With the above example configuration, the following are true:</p>
<ul>
<li>The price of “john” would be 2 * 10^8, since “john” falls into bucket 4 and has no punctuation or numerics.</li>
<li>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)</li>
<li>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)</li>
<li>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)</li>
<li>The namespace reveal <codeclass="highlighter-rouge">scriptSig</code> (with the namespace revealer’s public key), or one of its first 300 extended public keys</li>
<li>These transactions can only be sent between the <codeclass="highlighter-rouge">NAMESPACE_REVEAL</code> and <codeclass="highlighter-rouge">NAMESPACE_READY</code>.</li>
<li>The first <codeclass="highlighter-rouge">NAME_IMPORT</code> transaction <strong>must</strong> have a <codeclass="highlighter-rouge">scriptSig</code> input that matches the <codeclass="highlighter-rouge">NAMESPACE_REVEAL</code>’s second output (i.e. the reveal output).</li>
<li>Any subsequent <codeclass="highlighter-rouge">NAME_IMPORT</code> transactions <strong>may</strong> have a <codeclass="highlighter-rouge">scriptSig</code> input whose public key is one of the first 300 extended public keys from the <codeclass="highlighter-rouge">NAMESPACE_REVEAL</code>’s <codeclass="highlighter-rouge">scriptSig</code> public key.</li>
embedConfig: undefined, // {'url':undefined,'contentBlock':'.page-content-body'}, // if url is given the page will change to that URL and look for the content block there to insert the results
fullScreenConfig: undefined, // {trigger: '#ss360-search-trigger', caption: 'Search this site'}, trigger is the CSS selector to the element that starts the search full screen overlay and searchCaption the caption on the full screen search page
caption: 'Found #COUNT# search results for \"#QUERY#\"', // the caption of the search results
group: true, // whether results should be grouped if content groups are available
filters: undefined,
num: 96, // the maximum number of search results to be shown
highlightQueryTerms: true, // whether to highlight the query terms in search results
moreResultsButton: "Show more results", // HTML for the more results button, all results will be shown if this is null
noResultsText: 'Sorry, we have not found any matches for your query.', // the text to show when there are no results
queryCorrectionText: 'Did you mean "#CORRECTION#"?',
searchQueryParamName: 'ss360Query', // the name of the search query parameter
linksOpenNewTab: false, // should clicking on the result links open a new tab/window?
showSearchBoxLayover: true, //whether to show search box in search result layover
moreResultsPagingSize: 12, // the number of new results to show each time the more results button is pressed (max: 24)
orderByRelevanceText: "Relevance" // the text to be shown in order select box to describe 'order by relevance' option
},
suggestions: {
show: true, // whether to show search suggestions
maxQuerySuggestions: 3, // the maximum number of query suggestions
querySuggestionHeadline: undefined, // the headline of the query suggestions, leave blank if no headline should be shown
emptyQuerySuggestions: undefined,
showImages: false, // show images in search suggestions
num: 6, // the maximum number of search suggestions to be shown
minChars: 3, // minimum number of characters before the suggestions shows, default: 3,
maxWidth: 'auto', // the maximum width of the suggest box, default: as wide as the input box, at least 275px
throttleTime: 300, // the number of milliseconds before the suggest is triggered after finished input, default: 300ms
extraHtml: undefined, // extra HTML code that is shown in each search suggest, you can even show values of datapoints here,
highlight: true, // whether matched words should be highlighted, default: true