<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://rodentrabies.com/feed.xml" rel="self" type="application/atom+xml" /><link href="https://rodentrabies.com/" rel="alternate" type="text/html" /><updated>2025-09-03T09:56:29+00:00</updated><id>https://rodentrabies.com/feed.xml</id><title type="html">rodentrabies</title><subtitle>Bitcoin, Lisp, software, economics... bc1qjnlky63epenkuaqes6n28s0zzywyg2q80u28vg</subtitle><author><name>rodentrabies</name><email>rodentrabies@protonmail.com</email></author><entry><title type="html">Querying Bitcoin data using RDF and AllegroGraph</title><link href="https://rodentrabies.com/jekyll/update/2019/10/10/querying-bitcoin-data-using-rdf.html" rel="alternate" type="text/html" title="Querying Bitcoin data using RDF and AllegroGraph" /><published>2019-10-10T19:34:00+00:00</published><updated>2019-10-10T19:34:00+00:00</updated><id>https://rodentrabies.com/jekyll/update/2019/10/10/querying-bitcoin-data-using-rdf</id><content type="html" xml:base="https://rodentrabies.com/jekyll/update/2019/10/10/querying-bitcoin-data-using-rdf.html"><![CDATA[<h2 id="introduction">Introduction</h2>
<p>Bitcoin operates by maintaining the data about all value transfers in a single
database, whose integrity and consistency is ensured by a set of cryptographic
protocols, the most important of which is called <strong>PoW</strong> (<em>Proof-of-Work</em>). This
data forms a graph with two general types of relations:</p>
<ul>
  <li><em>block membership relations</em> introduce ordering into the transaction data by
building a timestamped sequence (chain) of groups (blocks) of transactions,
and are merely used to verify the integrity and consistency of the database
according to the network consensus rules;</li>
  <li><em>transaction chaining relations</em> provide monetary properties for Bitcoin
system by creating links between chunks of value, tracking their movement from
the moment of generation during mining to point in time when they are used.</li>
</ul>

<p>By definition, Bitcoin chain data is an immutable set of public records that
represent its complete transaction history, which makes it an important global
resource, while its transparent graph structure makes it an easy subject of
various analysis methods. These methods are actively researched from two
opposite points of view: as means of undermining privacy of the transaction data
(see Bitfury’s <a href="https://crystalblockchain.com/">Crystal</a>) and as means of protecting against that (see
<a href="https://en.bitcoin.it/wiki/CoinJoin">CoinJoin</a> and Samourai’s <a href="https://samouraiwallet.com/whirlpool">Whirlpool</a> technologies).</p>

<p>One of the simplest means of graph analysis is graph querying with specialized
querying languages like <a href="https://en.wikipedia.org/wiki/SPARQL">SPARQL</a>. Moreover, there exists a set of powerful
standard tools for representing and exploring graph data with such languages:
<a href="https://en.wikipedia.org/wiki/Resource_Description_Framework">RDF - Resource Description Framework</a>.</p>

<p>In order to be able to use SPARQL for loading and querying Bitcoin database, we
need to build an RDF model which defines the properties of Bitcoin entities as
well as relations between them. To make our approach as general as possible, we
will model Bitcoin data directly from its native representation. This model can
then be used as a guideline for converting the Bitcoin data into a set of
triples suitable for storing in a graph database. We will be using AllegroGraph
for the purpose of storing the triples and as a querying engine.</p>

<h2 id="block-data-model">Block data model</h2>
<p>In all Turtle examples we assume the following standard namespaces are available:</p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">RDF</code> (http://www.w3.org/1999/02/22-rdf-syntax-ns#);</li>
  <li><code class="language-plaintext highlighter-rouge">RDFS</code> (http://www.w3.org/2000/01/rdf-schema#);</li>
  <li><code class="language-plaintext highlighter-rouge">XSD</code> (http://www.w3.org/2001/XMLSchema#);</li>
  <li><code class="language-plaintext highlighter-rouge">OWL</code> (http://www.w3.org/2002/07/owl#).</li>
</ul>

<p>These resources together form a powerful standard language for describing RDF
models and in particular provide all necessary definitions to build the Bitcoin
model.</p>

<p>Bitcoin block is a container for transactions, whose main consensus property is
a hash of the previous block (some properties omitted for simplicy):</p>
<div class="language-turtle highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nl">&lt;Block&gt;</span><span class="w">
        </span><span class="nn">rdf:</span><span class="n">type</span><span class="w">     </span><span class="nn">rdfs:</span><span class="n">Class</span><span class="p">;</span><span class="w">

</span><span class="nl">&lt;hash&gt;</span><span class="w">
        </span><span class="nn">rdf:</span><span class="n">type</span><span class="w">     </span><span class="nn">rdfs:</span><span class="n">Property</span><span class="p">;</span><span class="w">
        </span><span class="nn">rdfs:</span><span class="n">comment</span><span class="w"> </span><span class="s">"Hex-encoded double-hash of the block header that is used in PoW to chain blocks."</span><span class="p">;</span><span class="w">
        </span><span class="nn">rdfs:</span><span class="n">domain</span><span class="w">  </span><span class="nl">&lt;Block&gt;</span><span class="p">;</span><span class="w">
        </span><span class="nn">rdfs:</span><span class="n">range</span><span class="w">   </span><span class="nn">xsd:</span><span class="n">string</span><span class="p">.</span><span class="w">

</span><span class="nl">&lt;height&gt;</span><span class="w">
        </span><span class="nn">rdf:</span><span class="n">type</span><span class="w">     </span><span class="nn">rdfs:</span><span class="n">Property</span><span class="p">;</span><span class="w">
        </span><span class="nn">rdfs:</span><span class="n">comment</span><span class="w"> </span><span class="s">"Height of the block is an index of the block in the chain, starting from 0."</span><span class="p">;</span><span class="w">
        </span><span class="nn">rdfs:</span><span class="n">domain</span><span class="w">  </span><span class="nl">&lt;Block&gt;</span><span class="p">;</span><span class="w">
        </span><span class="nn">rdfs:</span><span class="n">range</span><span class="w">   </span><span class="nn">xsd:</span><span class="n">integer</span><span class="p">.</span><span class="w">

</span><span class="nl">&lt;transaction&gt;</span><span class="w">
        </span><span class="nn">rdf:</span><span class="n">type</span><span class="w">     </span><span class="nn">rdfs:</span><span class="n">Property</span><span class="p">;</span><span class="w">
        </span><span class="nn">rdfs:</span><span class="n">comment</span><span class="w"> </span><span class="s">"Transaction-Block membership relation."</span><span class="p">;</span><span class="w">
        </span><span class="nn">rdfs:</span><span class="n">domain</span><span class="w">  </span><span class="nl">&lt;Block&gt;</span><span class="p">;</span><span class="w">
        </span><span class="nn">rdfs:</span><span class="n">range</span><span class="w">   </span><span class="nl">&lt;Transaction&gt;</span><span class="p">.</span><span class="w">

</span><span class="nl">&lt;prevBlock&gt;</span><span class="w">
        </span><span class="nn">rdf:</span><span class="n">type</span><span class="w">      </span><span class="nn">rdfs:</span><span class="n">Property</span><span class="p">;</span><span class="w">
        </span><span class="nn">rdfs:</span><span class="n">comment</span><span class="w">  </span><span class="s">"Introduce ordering into set of Bitcoin blocks."</span><span class="p">;</span><span class="w">
        </span><span class="nn">rdfs:</span><span class="n">domain</span><span class="w">   </span><span class="nl">&lt;Block&gt;</span><span class="p">;</span><span class="w">
        </span><span class="nn">rdfs:</span><span class="n">range</span><span class="w">    </span><span class="nl">&lt;Block&gt;</span><span class="p">.</span><span class="w">

</span><span class="nl">&lt;nextBlock&gt;</span><span class="w">
        </span><span class="nn">rdf:</span><span class="n">type</span><span class="w">      </span><span class="nn">rdfs:</span><span class="n">Property</span><span class="p">;</span><span class="w">
        </span><span class="nn">rdfs:</span><span class="n">comment</span><span class="w">  </span><span class="s">"Helper inverse of prevBlock property."</span><span class="p">;</span><span class="w">
        </span><span class="nn">rdfs:</span><span class="n">domain</span><span class="w">   </span><span class="nl">&lt;Block&gt;</span><span class="p">;</span><span class="w">
        </span><span class="nn">rdfs:</span><span class="n">range</span><span class="w">    </span><span class="nl">&lt;Block&gt;</span><span class="p">;</span><span class="w">
        </span><span class="nn">owl:</span><span class="n">inverseOf</span><span class="w"> </span><span class="nl">&lt;prevBlock&gt;</span><span class="p">.</span><span class="w">
</span></code></pre></div></div>

<p>Value in Bitcoin is represented by a set of entities called <em>transaction
outputs</em> - pairs <code class="language-plaintext highlighter-rouge">(&lt;amount&gt; &lt;lock script&gt;)</code> where <code class="language-plaintext highlighter-rouge">&lt;lock script&gt;</code> is a certain
condition expressed in a simple stack language called Bitcoin script:</p>
<div class="language-turtle highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nl">&lt;TxOutput&gt;</span><span class="w">
        </span><span class="nn">rdf:</span><span class="n">type</span><span class="w">     </span><span class="nn">rdfs:</span><span class="n">Class</span><span class="p">;</span><span class="w">

</span><span class="nl">&lt;amount&gt;</span><span class="w">
        </span><span class="nn">rdf:</span><span class="n">type</span><span class="w">     </span><span class="nn">rdfs:</span><span class="n">Property</span><span class="p">;</span><span class="w">
        </span><span class="nn">rdfs:</span><span class="n">comment</span><span class="w"> </span><span class="s">"Amount of atomic units locked in this UTXO."</span><span class="p">;</span><span class="w">
        </span><span class="nn">rdfs:</span><span class="n">domain</span><span class="w">  </span><span class="nl">&lt;TxOutput&gt;</span><span class="p">;</span><span class="w">
        </span><span class="nn">rdfs:</span><span class="n">range</span><span class="w">   </span><span class="nn">xsd:</span><span class="n">integer</span><span class="p">.</span><span class="w">

</span><span class="nl">&lt;lockScript&gt;</span><span class="w">
        </span><span class="nn">rdf:</span><span class="n">type</span><span class="w">     </span><span class="nn">rdfs:</span><span class="n">Property</span><span class="p">;</span><span class="w">
        </span><span class="nn">rdfs:</span><span class="n">comment</span><span class="w"> </span><span class="s">"Script that describes an unlocking condition of the given output."</span><span class="p">;</span><span class="w">
        </span><span class="nn">rdfs:</span><span class="n">domain</span><span class="w">  </span><span class="nl">&lt;TxOutput&gt;</span><span class="p">;</span><span class="w">
        </span><span class="nn">rdfs:</span><span class="n">range</span><span class="w">   </span><span class="nl">&lt;Script&gt;</span><span class="p">.</span><span class="w">
</span></code></pre></div></div>

<p>Value from an output can be transfered by providing an entity called
<em>transaction input</em> - a triple <code class="language-plaintext highlighter-rouge">(&lt;transaction id&gt; &lt;output index&gt; &lt;unlock
script&gt;)</code> such that <code class="language-plaintext highlighter-rouge">&lt;lock script&gt;</code> and <code class="language-plaintext highlighter-rouge">&lt;unlock script&gt;</code> when combined, must
evaluate to 1, forming a proof of ownership over the given value (some
properties omitted for brevity):</p>
<div class="language-turtle highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nl">&lt;TxInput&gt;</span><span class="w">
        </span><span class="nn">rdf:</span><span class="n">type</span><span class="w">     </span><span class="nn">rdfs:</span><span class="n">Class</span><span class="p">;</span><span class="w">

</span><span class="nl">&lt;outputHash&gt;</span><span class="w">
        </span><span class="nn">rdf:</span><span class="n">type</span><span class="w">     </span><span class="nn">rdfs:</span><span class="n">Property</span><span class="p">;</span><span class="w">
        </span><span class="nn">rdfs:</span><span class="n">comment</span><span class="w"> </span><span class="s">"Hash of the transaction whose output is spent by this input."</span><span class="p">;</span><span class="w">
        </span><span class="nn">rdfs:</span><span class="n">domain</span><span class="w">  </span><span class="nl">&lt;TxInput&gt;</span><span class="p">;</span><span class="w">
        </span><span class="nn">rdfs:</span><span class="n">range</span><span class="w">   </span><span class="nn">xsd:</span><span class="n">string</span><span class="p">.</span><span class="w">

</span><span class="nl">&lt;outputIndex&gt;</span><span class="w">
        </span><span class="nn">rdf:</span><span class="n">type</span><span class="w">     </span><span class="nn">rdfs:</span><span class="n">Property</span><span class="p">;</span><span class="w">
        </span><span class="nn">rdfs:</span><span class="n">comment</span><span class="w"> </span><span class="s">"Index of the transcation output which is spent by this input."</span><span class="p">;</span><span class="w">
        </span><span class="nn">rdfs:</span><span class="n">domain</span><span class="w">  </span><span class="nl">&lt;TxInput&gt;</span><span class="p">;</span><span class="w">
        </span><span class="nn">rdfs:</span><span class="n">range</span><span class="w">   </span><span class="nn">xsd:</span><span class="n">integer</span><span class="p">.</span><span class="w">

</span><span class="nl">&lt;unlockScript&gt;</span><span class="w">
        </span><span class="nn">rdf:</span><span class="n">type</span><span class="w">     </span><span class="nn">rdfs:</span><span class="n">Property</span><span class="p">;</span><span class="w">
        </span><span class="nn">rdfs:</span><span class="n">comment</span><span class="w"> </span><span class="s">"Script that is appended to locking script in order to unlock the UTXO."</span><span class="p">;</span><span class="w">
        </span><span class="nn">rdfs:</span><span class="n">domain</span><span class="w">  </span><span class="nl">&lt;TxInput&gt;</span><span class="p">;</span><span class="w">
        </span><span class="nn">rdfs:</span><span class="n">range</span><span class="w">   </span><span class="nl">&lt;Script&gt;</span><span class="p">.</span><span class="w">
</span></code></pre></div></div>

<p>All the value in the Bitcoin system is contained in a <em>UTXO</em> (<em>Unspent
Transaction Output</em>) set - a set of transaction outputs, for which no inputs
exist within the system so far.</p>

<p>Finally, Bitcoin transaction is just a special record that represents a
destruction of a subset of existing UTXOs and creation of new UTXOs under the
condition that the sum of the amounts in the destroyed UTXOs is larger than or
equal to the sum of created ones (some properties omitted for brevity):</p>
<div class="language-turtle highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nl">&lt;Transaction&gt;</span><span class="w">
        </span><span class="nn">rdf:</span><span class="n">type</span><span class="w">     </span><span class="nn">rdfs:</span><span class="n">Class</span><span class="p">;</span><span class="w">

</span><span class="nl">&lt;txid&gt;</span><span class="w">
        </span><span class="nn">rdf:</span><span class="n">type</span><span class="w">     </span><span class="nn">rdfs:</span><span class="n">Property</span><span class="p">;</span><span class="w">
        </span><span class="nn">rdfs:</span><span class="n">comment</span><span class="w"> </span><span class="s">"Hash of the transaction which is used to uniquely identify it."</span><span class="p">;</span><span class="w">
        </span><span class="nn">rdfs:</span><span class="n">domain</span><span class="w">  </span><span class="nl">&lt;Transaction&gt;</span><span class="p">;</span><span class="w">
        </span><span class="nn">rdfs:</span><span class="n">range</span><span class="w">   </span><span class="nn">xsd:</span><span class="n">string</span><span class="p">.</span><span class="w">

</span><span class="nl">&lt;input&gt;</span><span class="w">
        </span><span class="nn">rdf:</span><span class="n">type</span><span class="w">     </span><span class="nn">rdfs:</span><span class="n">Property</span><span class="p">;</span><span class="w">
        </span><span class="nn">rdfs:</span><span class="n">comment</span><span class="w"> </span><span class="s">"Input-Transaction membership relation."</span><span class="p">;</span><span class="w">
        </span><span class="nn">rdfs:</span><span class="n">domain</span><span class="w">  </span><span class="nl">&lt;Transaction&gt;</span><span class="p">;</span><span class="w">
        </span><span class="nn">rdfs:</span><span class="n">range</span><span class="w">   </span><span class="nl">&lt;Input&gt;</span><span class="p">.</span><span class="w">

</span><span class="nl">&lt;output&gt;</span><span class="w">
        </span><span class="nn">rdf:</span><span class="n">type</span><span class="w">     </span><span class="nn">rdfs:</span><span class="n">Property</span><span class="p">;</span><span class="w">
        </span><span class="nn">rdfs:</span><span class="n">comment</span><span class="w"> </span><span class="s">"Output-Transaction membership relation."</span><span class="p">;</span><span class="w">
        </span><span class="nn">rdfs:</span><span class="n">domain</span><span class="w">  </span><span class="nl">&lt;Transaction&gt;</span><span class="p">;</span><span class="w">
        </span><span class="nn">rdfs:</span><span class="n">range</span><span class="w">   </span><span class="nl">&lt;Output&gt;</span><span class="p">.</span><span class="w">
</span></code></pre></div></div>

<p>The following Turtle example demonstrates how this RDF model can be used to
represent complete chain database (block given is a <em>genesis</em> block - the first
block in the mainnet Bitcoin chain; script strings omitted for brevity):</p>
<div class="language-turtle highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">@prefix</span><span class="w"> </span><span class="nn">:</span><span class="w"> </span><span class="nl">&lt;https://raw.githubusercontent.com/franzinc/agraph-examples/master/data/bitcoin/model.ttl#&gt;</span><span class="w">
</span><span class="kd">@prefix</span><span class="w"> </span><span class="nn">btc:</span><span class="w"> </span><span class="nl">&lt;bitcoin://&gt;</span><span class="w">

</span><span class="nn">btc:</span><span class="n">blk0
</span><span class="w">    </span><span class="nn">:</span><span class="n">height</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w">
    </span><span class="nn">:</span><span class="n">hash</span><span class="w"> </span><span class="s">"000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"</span><span class="p">;</span><span class="w">
    </span><span class="nn">:</span><span class="n">time</span><span class="w"> </span><span class="mi">1231006505</span><span class="p">;</span><span class="w">
    </span><span class="nn">:</span><span class="n">version</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span><span class="w">
    </span><span class="nn">:</span><span class="n">transaction</span><span class="w"> </span><span class="nn">btc:</span><span class="mi">4</span><span class="n">a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b</span><span class="p">.</span><span class="w">

</span><span class="nn">btc:</span><span class="mi">4</span><span class="n">a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b
</span><span class="w">    </span><span class="nn">:</span><span class="n">lockTime</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w">
    </span><span class="nn">:</span><span class="n">input</span><span class="w"> </span><span class="p">[</span><span class="nn">:</span><span class="n">unlockScript</span><span class="w"> </span><span class="s">"..."</span><span class="p">.];</span><span class="w">
    </span><span class="nn">:</span><span class="n">output</span><span class="w"> </span><span class="p">[</span><span class="nn">:</span><span class="n">amount</span><span class="w"> </span><span class="mi">5000000000</span><span class="p">;</span><span class="w"> </span><span class="nn">:</span><span class="n">lockScript</span><span class="w"> </span><span class="s">"..."</span><span class="p">.].</span><span class="w">
</span></code></pre></div></div>

<h2 id="loading-bitcoin-data">Loading Bitcoin data</h2>
<p>In order to be able to run queries, we first need to prepare a repository with
chain data. We will be using a simple Python tool for loading the chain data
into the AllegroGraph instance, which can be found in the
<a href="https://github.com/franzinc/agraph-examples/tree/master/data/bitcoin"><code class="language-plaintext highlighter-rouge">data/bitcoin</code></a> directory of the
<a href="https://github.com/franzinc/agraph-examples"><code class="language-plaintext highlighter-rouge">agraph-examples</code></a> repository on GitHub along with the model
we described above.</p>

<p>The following examples assume AllegroGraph triple store and assume it is already
installed and running on the target machine. The following AG instance settings
settings are assumed as well:</p>
<ul>
  <li><em>host</em>: <code class="language-plaintext highlighter-rouge">localhost</code> (default);</li>
  <li><em>port</em>: <code class="language-plaintext highlighter-rouge">10035</code> (default);</li>
  <li><em>username</em>: <code class="language-plaintext highlighter-rouge">aguser</code>;</li>
  <li><em>password</em>: <code class="language-plaintext highlighter-rouge">agpassword</code>.</li>
</ul>

<p>We need to make sure we have an access to a running <code class="language-plaintext highlighter-rouge">bitcoind</code> instance with RPC
port open. We assume following <code class="language-plaintext highlighter-rouge">bitcoind</code> settings:</p>
<ul>
  <li><em>host</em>: <code class="language-plaintext highlighter-rouge">localhost</code> (default);</li>
  <li><em>port</em>: <code class="language-plaintext highlighter-rouge">8332</code> (default);</li>
  <li><em>username</em>: <code class="language-plaintext highlighter-rouge">btcuser</code>;</li>
  <li><em>password</em>: <code class="language-plaintext highlighter-rouge">btcpassword</code>.</li>
</ul>

<p>First, we will install the tool by cloning the
<a href="https://github.com/franzinc/agraph-examples"><code class="language-plaintext highlighter-rouge">agraph-examples</code></a> repository, setting up a virtual
environment and installing the dependencies:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git clone https://github.com/franzinc/agraph-examples
<span class="nb">cd </span>agraph-examples/data/bitcoin
python3 <span class="nt">-m</span> venv <span class="nb">.</span>
<span class="nb">source</span> ./bin/activate
pip3 <span class="nb">install</span> <span class="nt">-r</span> requirements.txt
</code></pre></div></div>

<p>Now we are good to go. The following command starts the process of loading
bitcoin chain data into a clean AG repository named <code class="language-plaintext highlighter-rouge">bitcoin</code> using 4 loader
processes:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>./convert.py <span class="se">\</span>
    <span class="nt">--source</span><span class="o">=</span>http://btcuser:btcpassword@localhost:8332 <span class="se">\</span>
    <span class="nt">--destination</span><span class="o">=</span>http://aguser:agpassword@localhost:10035 <span class="se">\</span>
    <span class="nt">--name</span><span class="o">=</span>bitcoin <span class="se">\</span>
    <span class="nt">--workers</span><span class="o">=</span>4 <span class="se">\</span>
    <span class="nt">--clear</span>
</code></pre></div></div>

<p>Note that loading the whole Bitcoin chain takes quite a lot of time and
space. Using the following setup:</p>

<ul>
  <li>
    <p>machine running the loader - 2 x 4-core Intel(R) Xeon(R) L5420 @ 2.50GHz, 32
Gb of memory,</p>
  </li>
  <li>
    <p>machine running the AllegroGraph instance - 2 x 6-core AMD Opteron(tm) 2439 @
2.80GHz SE, 64 Gb of memory,</p>
  </li>
</ul>

<p>we were able to load 80% of all chain data in approximately 14 days. The disk
space required for the 80% chain database, which contains 11.5 billion triples,
is 1.1 Tb, around 4 times more than for a raw binary Bitcoin database maintained
by the <code class="language-plaintext highlighter-rouge">bitcoind</code> node, which at the moment of writing takes around 270
Gb. Given these numbers, for experimenting purposes, it might make sense to load
only a subset of blocks we are interested in by using the
<code class="language-plaintext highlighter-rouge">--start-height</code>/<code class="language-plaintext highlighter-rouge">--end-height</code> parameters for the <code class="language-plaintext highlighter-rouge">convert</code> tool:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>./convert.py <span class="se">\</span>
    <span class="nt">--source</span><span class="o">=</span>http://btcuser:btcpassword@localhost:8332 <span class="se">\</span>
    <span class="nt">--destination</span><span class="o">=</span>http://aguser:agpassword@localhost:10035 <span class="se">\</span>
    <span class="nt">--name</span><span class="o">=</span>bitcoin <span class="se">\</span>
    <span class="nt">--workers</span><span class="o">=</span>4 <span class="se">\</span>
    <span class="nt">--clear</span> <span class="se">\</span>
    <span class="nt">--start-height</span><span class="o">=</span>570000 <span class="se">\</span>
    <span class="nt">--end-height</span><span class="o">=</span>580000
</code></pre></div></div>

<h2 id="example-queries">Example queries</h2>
<p>Following are the examples of using SPARQL to extract different information
about block data:</p>
<ul>
  <li>number of known blocks:
    <div class="language-sparql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">PREFIX</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="nn">&lt;https://raw.githubusercontent.com/franzinc/agraph-examples/master/data/bitcoin/model.ttl#&gt;</span><span class="w">
</span><span class="k">SELECT</span><span class="w"> </span><span class="p">(</span><span class="nb">COUNT</span><span class="p">(</span><span class="o">*</span><span class="p">)</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="nv">?count</span><span class="p">)</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nv">?b</span><span class="w"> </span><span class="k">a</span><span class="w"> </span><span class="nn">btcm</span><span class="o">:</span><span class="ss">Block</span><span class="p">.</span><span class="w"> </span><span class="p">}</span><span class="w">
</span></code></pre></div>    </div>
  </li>
  <li>total number of transactions:
    <div class="language-sparql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">PREFIX</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="nn">&lt;https://raw.githubusercontent.com/franzinc/agraph-examples/master/data/bitcoin/model.ttl#&gt;</span><span class="w">
</span><span class="k">SELECT</span><span class="w"> </span><span class="p">(</span><span class="nb">COUNT</span><span class="p">(</span><span class="o">*</span><span class="p">)</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="nv">?count</span><span class="p">)</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nv">?tx</span><span class="w"> </span><span class="k">a</span><span class="w"> </span><span class="nn">btcm</span><span class="o">:</span><span class="ss">Transaction</span><span class="p">.</span><span class="w"> </span><span class="p">}</span><span class="w">
</span></code></pre></div>    </div>
  </li>
  <li>transaction in block 570001:
    <div class="language-sparql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">PREFIX</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="nn">&lt;https://raw.githubusercontent.com/franzinc/agraph-examples/master/data/bitcoin/model.ttl#&gt;</span><span class="w">
</span><span class="k">SELECT</span><span class="w"> </span><span class="nv">?txid</span><span class="w">
</span><span class="k">WHERE</span><span class="w"> </span><span class="p">{</span><span class="w">
  </span><span class="nv">?b</span><span class="w"> </span><span class="k">a</span><span class="w"> </span><span class="o">:</span><span class="ss">Block</span><span class="p">.</span><span class="w">
  </span><span class="nv">?b</span><span class="w"> </span><span class="o">:</span><span class="ss">height</span><span class="w"> </span><span class="s2">"570001"</span><span class="o">^^</span><span class="nn">xsd</span><span class="o">:</span><span class="ss">int</span><span class="p">.</span><span class="w">
  </span><span class="nv">?b</span><span class="w"> </span><span class="o">:</span><span class="ss">transaction</span><span class="w"> </span><span class="nv">?tx</span><span class="p">.</span><span class="w">
  </span><span class="nv">?tx</span><span class="w"> </span><span class="o">:</span><span class="ss">txid</span><span class="w"> </span><span class="nv">?txid</span><span class="p">.</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div>    </div>
  </li>
  <li>transactions sending more than 1000 BTC:
    <div class="language-sparql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">PREFIX</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="nn">&lt;https://raw.githubusercontent.com/franzinc/agraph-examples/master/data/bitcoin/model.ttl#&gt;</span><span class="w">
</span><span class="k">SELECT</span><span class="w"> </span><span class="nv">?tx</span><span class="w">
</span><span class="k">WHERE</span><span class="w"> </span><span class="p">{</span><span class="w">
  </span><span class="nv">?b</span><span class="w"> </span><span class="k">a</span><span class="w"> </span><span class="o">:</span><span class="ss">Block</span><span class="p">.</span><span class="w">
  </span><span class="nv">?b</span><span class="w"> </span><span class="o">:</span><span class="ss">transaction</span><span class="w"> </span><span class="nv">?tx</span><span class="p">.</span><span class="w">
  </span><span class="nv">?tx</span><span class="w"> </span><span class="o">:</span><span class="ss">output</span><span class="w"> </span><span class="nv">?out</span><span class="p">.</span><span class="w">
  </span><span class="nv">?out</span><span class="w"> </span><span class="o">:</span><span class="ss">amount</span><span class="w"> </span><span class="nv">?amt</span><span class="p">.</span><span class="w">
</span><span class="p">}</span><span class="w">
</span><span class="k">GROUP</span><span class="w"> </span><span class="k">BY</span><span class="w"> </span><span class="nv">?tx</span><span class="w">
</span><span class="k">HAVING</span><span class="w"> </span><span class="p">(</span><span class="nb">SUM</span><span class="p">(</span><span class="nv">?amt</span><span class="p">)</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="mi">100000000000</span><span class="p">)</span><span class="w">
</span></code></pre></div>    </div>
  </li>
  <li>transactions sending BTC to Pirate Bay’s address:
    <div class="language-sparql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">PREFIX</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="nn">&lt;https://raw.githubusercontent.com/franzinc/agraph-examples/master/data/bitcoin/model.ttl#&gt;</span><span class="w">
</span><span class="k">SELECT</span><span class="w"> </span><span class="nv">?tx</span><span class="w">
</span><span class="k">WHERE</span><span class="w"> </span><span class="p">{</span><span class="w">
  </span><span class="nv">?tx</span><span class="w"> </span><span class="o">:</span><span class="ss">output</span><span class="w"> </span><span class="nv">?out</span><span class="p">.</span><span class="w">
  </span><span class="nv">?out</span><span class="w"> </span><span class="o">:</span><span class="ss">lockScript</span><span class="w"> </span><span class="nv">?s</span><span class="p">.</span><span class="w">
  </span><span class="k">FILTER</span><span class="w"> </span><span class="nb">REGEX</span><span class="w"> </span><span class="p">(</span><span class="nv">?s</span><span class="p">,</span><span class="w"> </span><span class="s2">"&lt;tpb address&gt;"</span><span class="p">).</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div>    </div>
  </li>
</ul>]]></content><author><name>rodentrabies</name><email>rodentrabies@protonmail.com</email></author><category term="jekyll" /><category term="update" /><summary type="html"><![CDATA[Introduction Bitcoin operates by maintaining the data about all value transfers in a single database, whose integrity and consistency is ensured by a set of cryptographic protocols, the most important of which is called PoW (Proof-of-Work). This data forms a graph with two general types of relations: block membership relations introduce ordering into the transaction data by building a timestamped sequence (chain) of groups (blocks) of transactions, and are merely used to verify the integrity and consistency of the database according to the network consensus rules; transaction chaining relations provide monetary properties for Bitcoin system by creating links between chunks of value, tracking their movement from the moment of generation during mining to point in time when they are used.]]></summary></entry><entry><title type="html">Go 2 generics draft notes</title><link href="https://rodentrabies.com/jekyll/update/2018/09/08/go-2-generics-draft-notes.html" rel="alternate" type="text/html" title="Go 2 generics draft notes" /><published>2018-09-08T08:36:00+00:00</published><updated>2018-09-08T08:36:00+00:00</updated><id>https://rodentrabies.com/jekyll/update/2018/09/08/go-2-generics-draft-notes</id><content type="html" xml:base="https://rodentrabies.com/jekyll/update/2018/09/08/go-2-generics-draft-notes.html"><![CDATA[<h2 id="introduction">Introduction</h2>

<p>Last week Go team published a page with detailed <a href="https://go.googlesource.com/proposal/+/master/design/go2draft.md">specification drafts</a> for
Go 2 generics and error handling tools. The proposal is both well-thought and
brave, since one of the main ideas is to introduce contract system akin to C++
concepts. Contracts, in Go parlance, are (possibly syntactically restricted)
named functions, parameterized both by value and by its type, which are used by
compiler to ensure some contract are held by types as stated. What’s great about
contracts is that the procedure of contract checking is very simple - since it’s
just a function body, compilers type-checks, compiles and then discards its body
and that’s it.</p>

<p>But, simplicity for the compiler often comes with the cost for the user. This
post is an attempt to analyze the proposal and collect any notes I made while
reading the document. The <a href="#syntax">Syntax</a> section gives few notes on the
proposed syntax, while <a href="#semantics">Semantics</a> section describes… well,
semantics.</p>

<h2 id="syntax">Syntax</h2>
<p>One of the most important <em>little</em> things about Go is a minimal and clean
syntax. Generally, proposal keeps it that way but there are a few moments that
make just a little bit too much in some places.</p>

<h4 id="function-type-parameter-declarations">Function type parameter declarations</h4>
<p>Since methods seem to not be having type parameters, for standalone functions
they can be declared in place of method receiver argument:</p>

<div class="language-golang highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">func</span> <span class="p">(</span><span class="k">type</span> <span class="n">T</span><span class="p">)</span> <span class="n">Print</span><span class="p">(</span><span class="n">slice</span> <span class="p">[]</span><span class="n">T</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">for</span> <span class="n">_</span><span class="p">,</span> <span class="n">v</span> <span class="n">in</span> <span class="k">range</span> <span class="n">slice</span> <span class="p">{</span>
        <span class="n">fmt</span><span class="o">.</span><span class="n">Printf</span><span class="p">(</span><span class="s">"%v"</span><span class="p">,</span> <span class="n">v</span><span class="p">)</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>This both simplifies the <code class="language-plaintext highlighter-rouge">(type ...)(parameters ...)</code> form and is more logical
from the point of view that type parameters and regular parameters should be
clearly separated. The problem is such a syntax is a little bit ambiguous
visually, but still it is much more simple from a notation point of view than
<code class="language-plaintext highlighter-rouge">(type ...)(parameters ...)</code> form.</p>

<h4 id="contract-as-another-type-of-type">Contract as another type of type</h4>
<p>To avoid Go 1 compatibility complexities with making contract a keyword,
contacts can be considered another type of type declaration, i.e. use syntax</p>

<div class="language-golang highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">type</span> <span class="n">Convertible</span><span class="p">(</span><span class="n">_</span> <span class="n">To</span><span class="p">,</span> <span class="n">f</span> <span class="n">From</span><span class="p">)</span> <span class="n">contract</span> <span class="p">{}</span>
</code></pre></div></div>

<p>This, however, may pose a semantic problem, since Go generally adheres to direct
mapping between types and memory representation of values: structs map to
sequences of named fields, interfaces map to double-pointer <code class="language-plaintext highlighter-rouge">(val, vtable)</code>
values, while contracts do not map to anything, since they are purely
compile-time constructs.</p>

<h2 id="semantics">Semantics</h2>

<h4 id="contracts-or-no-contracts">Contracts or no contracts?</h4>
<p>Stating it this far in the post may be strange, but one of the first notes I
made about contract proposal is that I actually don’t like the idea of having
function bodies that are not function bodies, which may be misleading. Imposing
restrictions on contract bodies requires extending Go’s grammar and having no
restrictions whatsoever may cause eye injuries while reading contract bodies
with <code class="language-plaintext highlighter-rouge">if</code>/<code class="language-plaintext highlighter-rouge">for</code>/<code class="language-plaintext highlighter-rouge">defer</code> statements. Allowing only assignment statements and
expressions in a contract body won’t prevent it from containing any logic beyond
pure declaration of a set of permitted operations, which can still be very
misleading to the reader.</p>

<p>Consider the following structures:</p>

<div class="language-golang highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">type</span> <span class="n">Pair</span> <span class="k">struct</span> <span class="p">{</span>
    <span class="n">first</span><span class="p">,</span> <span class="n">second</span> <span class="kt">int</span>
<span class="p">}</span>

<span class="k">type</span> <span class="n">Cons</span> <span class="k">struct</span> <span class="p">{</span>
    <span class="n">head</span><span class="p">,</span> <span class="n">tail</span> <span class="kt">int</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Just by looking at these declarations, we can tell that they are structurally
identical and, according to Go specifications, even have the same representation
in memory. In other words these two structures are <em>isomorphic</em> and even if we
have never worked with Lisp language and haven’t seen <code class="language-plaintext highlighter-rouge">Cons</code> structure before,
we can easily deduce how it behaves, since it’s isomorphic to the <code class="language-plaintext highlighter-rouge">Pair</code>, a
simple structure everyone knows.</p>

<p>Similarly, consider these two interfaces:</p>

<div class="language-golang highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">type</span> <span class="n">Index</span> <span class="k">interface</span> <span class="p">{</span>
    <span class="n">Clear</span><span class="p">(</span><span class="n">i</span> <span class="kt">int</span><span class="p">)</span>
    <span class="n">Set</span><span class="p">(</span><span class="n">i</span> <span class="kt">int</span><span class="p">,</span> <span class="n">value</span> <span class="kt">string</span><span class="p">)</span>
<span class="p">}</span>

<span class="k">type</span> <span class="n">StringMap</span> <span class="k">interface</span> <span class="p">{</span>
    <span class="n">Insert</span><span class="p">(</span><span class="n">k</span> <span class="kt">string</span><span class="p">,</span> <span class="n">value</span> <span class="k">interface</span><span class="p">{})</span>
    <span class="n">Remove</span><span class="p">(</span><span class="n">k</span> <span class="kt">string</span><span class="p">)</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Even though this is a deliberately hard example and operations in these
interfaces are completely different, they have the same signature structure and
thus can be deemed isomorphic and understood to perform a similar tasks of
including and changing some value at a given key.</p>

<p>Now, consider these two contracts:</p>

<div class="language-golang highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">contract</span> <span class="n">strseq1</span><span class="p">(</span><span class="n">x</span> <span class="n">T</span><span class="p">)</span> <span class="p">{</span>
	<span class="p">[]</span><span class="kt">byte</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
	<span class="n">T</span><span class="p">([]</span><span class="kt">byte</span><span class="p">{})</span>
	<span class="nb">len</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
<span class="p">}</span>

<span class="n">contract</span> <span class="n">strseq2</span><span class="p">(</span><span class="n">a</span> <span class="n">T</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">var</span> <span class="n">c</span> <span class="kt">int</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
    <span class="k">var</span> <span class="n">bs</span> <span class="p">[]</span><span class="kt">byte</span> <span class="o">=</span> <span class="p">[]</span><span class="kt">byte</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
    <span class="n">T</span><span class="p">(</span><span class="n">bs</span><span class="p">)</span>
<span class="p">}</span>
</code></pre></div></div>

<p>They declare the same set of operations, but in order to tell that you have to
place them side by side and do some thinking. It’s not easy to informally check
these two contracts are isomorphic, and it’s extremely hard to do this formally
(see <a href="https://en.wikipedia.org/wiki/Graph_isomorphism">Graph isomorphism</a>). In other words, structs and interfaces are
declarative and simple to understand while contracts are imperative, and in
order to understand a contract, you have to follow their statements. Still, all
they do, is just declare a set of operations on some types. Go already has
interfaces for that, so a more simple approach is to add operator methods, come
up with a way to restrict overloading and just go with interfaces.</p>

<h4 id="contracts-from-interfaces">Contracts from interfaces</h4>
<p>Assuming contracts are here to stay, we can compromise between contracts and
interfaces by allowing using interface names as contract names in declarations
in order to reuse trivial contract declarations, i.e. every interface
declaration should generate equivalent contract as shown below:</p>

<div class="language-golang highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">type</span> <span class="n">ReadWrite</span> <span class="k">interface</span> <span class="p">{</span> 
   <span class="n">Read</span><span class="p">()</span> <span class="kt">string</span>
   <span class="n">Write</span><span class="p">(</span><span class="kt">string</span><span class="p">)</span>
<span class="p">}</span>

<span class="n">contract</span> <span class="n">ReadWrite</span><span class="p">(</span><span class="n">x</span> <span class="n">T</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">val</span> <span class="n">s</span> <span class="kt">string</span> <span class="o">=</span> <span class="n">x</span><span class="o">.</span><span class="n">Read</span><span class="p">()</span>
    <span class="n">x</span><span class="o">.</span><span class="n">Write</span><span class="p">(</span><span class="n">s</span><span class="p">)</span>
<span class="p">}</span>
</code></pre></div></div>

<p>This will allow using interfaces for most cases where contracts describe just a
set of methods and resort to contracts only for hard case like conversions and
operators. An important consequence of such correspondence is standard library
of contracts automatically derived from standard interfaces.</p>

<h2 id="conclusion">Conclusion</h2>
<p>Current Go generics proposal is very well-though and goes to great extent to
avoid all the problems with parametric polymorphism systems in languages like
C++ and Java. Contracts are a very interesting concept (<em>no</em> pun intended), but
they have some semantic drawbacks that are not yet solved and may never have a
simple solution. Keeping that in mind, if there’s any change to substitute them
with clean and pure old interfaces, we should do our best to try to avoid adding
them to the language in the end as, once added, such features are very hard to
get rid of.</p>]]></content><author><name>rodentrabies</name><email>rodentrabies@protonmail.com</email></author><category term="jekyll" /><category term="update" /><summary type="html"><![CDATA[Introduction]]></summary></entry></feed>