OCaml-bitcoin is a
library offering an OCaml interface to the original Bitcoin client
API. It is a small and straightforward library, whose announcement would
normally warrant nothing more than a quick post on the caml-list.
However, given the controversy surrounding Bitcoin and my own conflicted view on the subject, I
reckon some extra words are in order.
The problem with Bitcoin
TL;DR: it's the deflation thing.
Economics is still, at best, a protoscience. This remark is not meant to be
snarky or dismissive of the entire discipline, however. Quite on the contrary —
it is simply the acknowledgement that grounding Economics on the great edifice
of science is a tremendously complex effort, which in all likelihood will
require several more decades before the prefix proto even begins to
lose its relevance. There are two main factors at play. First, the foundation
upon which Economics must be grounded — Psychology — is also still in the early
stages of shedding its own proto prefix. Second, one must consider the
enormous difficulty of conducting controlled experiments in Economics,
particularly as the scale moves into the realm of Macroeconomics.
Take for example the seemingly simple problem of determining whether an
electronic commodity with a fixed and finite supply can function as a viable
currency — the Bitcoin problem, essentially. Some decades from now (for
sufficiently large values of "some"), Behavioural economics
will have developed to the point that we are able to construct a highly
sophisticated simulated human that models actual human economic behaviour to a
close degree, and we should also have the computing power to simulate the
interaction of many millions of these "individuals". With such a tool in hand
we will be able to grasp all manners of emergent phenomena that arise in an
economy under different currency regimes. The Bitcoin problem and all its
variations will become experimentally testable, and the current bickering over
the feasibility of Bitcoin should become a settled matter.
We are very far from the sci-fi scenario described above, however, which is
mostly why there are several different schools of economic thought with often
diametrically opposed predictions and solutions (perhaps I'm being overly
charitable towards economists as a class, though; I reckon their most
significant disagreements have more to do with the blinders of ideology than
the genuine fog of a protoscience). Personally, I find that the most compelling
argument is made by those who argue against the viability of a
deflationary currency. The reasoning is fairly simple: suppose Bitcoin starts
to gain some traction, and becomes useful beyond the need to buy Alpaca socks.
Being limited in supply, one should expect Bitcoins to increase sharply in
value. However, Bitcoins are more than just run-of-the-mill scarce, as total
production is hard-capped at about 21 million coins (a number which should be
reached around 2140, though close to 90% of those coins will be generated
before this decade is out). Moreover, once attrition is factored in, the number
of usable Bitcoins will even slowly decrease from a maximum. Now, if you have
in hands a commodity which is increasing in value and has a fixed supply, you
could not be faulted for guessing its value can only continue to rise, and
therefore you would choose to hold on to your Bitcoins instead of spending
them. In addition, this commodity becomes an attractive choice for speculation
— people will acquire Bitcoins for the sole purpose of later selling them at a
higher price, without any intention of actually spending them to buy goods or
services. To give a concrete example, suppose you have acquired some Bitcoins
and find yourself in a future where Bitcoin is gaining traction and increasing
in value. Furthermore, you intend to purchase socks from some website offering
either Bitcoins or Euros as payment options. Which would you choose? I reckon
most people would opt to spend the currency that slowly decreases in value (the
Euro) over the one that is gaining value every day.
Why is the above scenario a bad thing for Bitcoin? First, because if people
are stashing Bitcoins under the mattress instead of actually using them as the
preferred means of payment on the Internet, then Bitcoin will have failed one
its primary goals, that of revolutionising online payments. I realise there may
be some for whom Bitcoin's primary goal is instead that of providing a
convenient store of value. For them, Bitcoin failing as a currency is not much
of an issue, since they see Bitcoin's usefulness as a currency merely as a
welcome side-effect. Besides this being a minority view (seriously, who wasn't
attracted to Bitcoin primarily because of its potential as a
truly revolutionary currency?), I think its premisse lies on very shaky ground.
Which brings me to my second point: I think it will be impossible to dissociate
Bitcoin's value from its usefulness as a currency. If people aren't actually
using Bitcoins for online purchases, fewer websites will have an incentive to
keep supporting it, and Bitcoin's usefulness as a currency will decrease.
Moreover, a currency whose value is fast changing — even if that change is
positive — is a pain to handle. The overall likely result would be a crash in
confidence in Bitcoin, and consequent sudden loss in value. Obviously,
supporters of Bitcoin's economic model argue against this outcome. For them, if
Bitcoin's value were to start rising so fast as to endanger its usefulness as a
currency, then the counteracting force would quickly nip the bubble in the bud,
forcing a correction and ensuring a fairly stable valuation over time (though
still slowly increasing over the long term).
At its heart, the disagreement about Bitcoin can therefore be reduced to
different estimations about the nature of the forces acting to push up or bring
down the value of the currency. Bitcoin supporter's argue that the forces form
a negative feedback loop, and thus Bitcoin should enjoy the stability required
to become a feasible currency and store of value. On the opposite corner,
Bitcoin's detractors argue that once we factor in the "madness of crowds" and
the human tendency towards herding behaviour, the Bitcoin system has an
inherent tendency towards positive feedbacks, sudden state reversals, and
therefore anything but stability. In other words, boom-bust cycles are part of
the nature of deflationary currencies.
As I've already stated, I find the detractor's argument more compelling.
Therefore, should Bitcoin start to get some traction and mainstream attention,
I expect we will see the formation of an impressive bubble followed by a
spectacular crash. Also to be expected during the ramp up stage are
pronouncements that "this time is different" and the customary denials of the
existence of a bubble. In many ways a repeat of the events of the Summer of
2011, but larger in size. We humans are a sorry lot.
At this point the reader may be asking, “If you really think
Bitcoin has such a serious flaw, why support it at all? Moreover, you cannot
fault people for construing the release of this library as a tacit endorsement,
now can you?”. My answer is that the Bitcoin idea has enough potential
to warrant support, even if in its current incarnation it may be doomed.
Moreover, it is crucial that if Bitcoin should fail, that it fails by its own
(dis)merit. The alternative — Bitcoin failing due to being outlawed, for
example — would rob us of a valuable lesson in economics. Finally, I still hope
that more mainstream visibility and the influx of newcomers may tip the balance
of the Bitcoin community in such a way that those who take seriously the
potential fatal flaw of a deflationary currency are no longer a minority.
Even if you disagree about my assessment, I hope I have at least conveyed
the reason why I'm genuinely curious about the outcome of the great Bitcoin
experiment, and thus why I would very much like to see it played out in full.
Though I may be leaning towards the "Bitcoin cannot work" camp, I've also made
clear that I'm fully aware of how difficult it is to predict the behaviour of
billions of complex entities interacting with each other. In other words, it
would not surprise me greatly if it turned out that I was wrong and that
Bitcoin could work after all.
On the upside: Bitcoin is transparency friendly
One underappreciated advantage of Bitcoin is the transparency it enables.
Suppose an organisation wanted to open its books to public scrutiny; the aim
might be to give donours an assurance that any donation is in fact received, or
to give tax authorities the guarantee that all income is accounted for. With
Bitcoin, the organisation simply has to make public a master address through
which all incoming payments are forwarded. Any donour or client can then use
the blockchain to verify that their payment reached the intended destination.
Similarly, tax authorities can verify compliance by making random anonymous
purchases and checking whether those transactions are properly forwarded to the
public master address.
The scheme outlined above does not even require that all payments use the
same address (which would be an accounting nightmare). Instead, the
organisation can generate a different receiving address for each transaction,
with the extra provision that after a certain period (say, one day), all the
coins received in that transaction would be used as inputs to another
transaction whose target address is the public master address. Though this adds
one extra layer of indirection, it still makes it trivial to verify that any
given payment is accounted for.
(Note that the low-level control over which transaction outputs are used as
inputs for new transactions is a feature introduced by the Raw Transactions API in the
recently released Bitcoin 0.7. OCaml-bitcoin has full support for this new API,
though users are advised to stand clear of it unless they have a good
understanding of the Bitcoin system.)
To say that there is an (infantile) level of anti-tax and anti-government
sentiment on the main Bitcoin Forum
would be an understatement. So yes, the irony that Bitcoin could become the tax
authority's best friend has not escaped me, and this is a realisation that I
find most amusing.
Technical notes concerning OCaml-bitcoin
Behind the scenes, OCaml-bitcoin works by making JSON-RPC calls over the
network to a running Bitcoin daemon offering the official client API. The
obvious alternatives would have been to bind to a C library such as Libbitcoin, or to build in
OCaml a full-blown implementation of a Bitcoin node. The former is an
uncomfortable proposition until such third-party libraries have been vetted by
time, whereas the latter — though without question a very interesting project
which I hope someone will embark on — would have required a time investment
orders of magnitude higher than what I had alloted to this side project.
Parsing and outputing JSON is handled via Yojson. For the most part, the fact that
JSON-RPC is the method of interfacing with the Bitcoin client is hidden from
users of OCaml-bitcoin. Ideally, it ought to be completely
hidden, and the only reason it's not is because this first release does not
convert all complex JSON objects into proper OCaml records. This seemed a
prudent choice given that the official client's API is still in flux, but it
may be fixed in a future release.
The API offered
by OCaml-bitcoin is nearly identical to the
original Bitcoin client API. The function names are the same, and so is the
set of mandatory/optional parameters. The main difference is that a couple of
calls have been split into two separate calls each. Namely,
getrawtransaction is split into getrawtransaction proper and
getrawtransaction_verbose, whereas getwork is split between
getwork_with_data and getwork_without_data. The reason for
splitting is that the original calls have very different behaviour and result
depending on the presence of an optional parameter, and therefore in my opinion
these should have been different calls to start with. Note that OCaml-bitcoin's
API documentation includes a fairly complete description of each call, and
fixes some of the mistakes and ambiguities found in the Bitcoin wiki. You may
find it a useful resource even if you have no intention of using
OCaml-bitcoin.
It should be noted that the official Bitcoin client parses incoming JSON-RPC
calls in a brain-damaged manner. Essentially, all parameters are parsed by
position, including optional parameters. This means that if you want to provide
the optional parameter at position n, then you are obliged to also
provide the optional parameter at position n-1, even if you are happy
with the latter's default value. I tried to hide this brain damage from the
OCaml-bitcoin API by internally using default values equal to those assigned by
the Bitcoin client. There are however two calls where this is simply not
possible: listsinceblock and signrawtransaction. If you wish
to provide optional parameters to these functions make sure you obey the n
requires n-1 rule, or you'll get a runtime error.
A minor rant concerning the use of floats for monetary values is also in
order. Though internally the official Bitcoin client uses 64-bit integers for
amounts (the integer value being the multiple of the base BTC unit, which is
equal to 10 nanoBTC and informally called a "Satoshi"), the designer
of the JSON-RPC API decided to convert these amounts into floats. Though there
may be enough precision for this not to be much of an issue if proper
care is taken, it still opens the door to improper use. Moreover, since
users of the API are bound to use internally either 64-bit integers (the choice
I made for OCaml-bitcoin) or some special fixed-decimal type, the floats will
have to be converted back into some sensible format anyway. Therefore, the
decision to choose floats for serialising BTC amounts strikes me as a poor
one.
The actual communication with the Bitcoin client requires an implementation
of HTTP's POST method on the OCaml side. While for many applications it would
be convenient if OCaml-bitcoin were to provide a Lwt-friendly API, for others being forced to live
under Lwt's monad would be an unwelcome outcome (for the purposes of this
discussion, you may replace all references to "Lwt" with "Async"). For this reason, I
decided not to impose any actual HTTP client implementation. Instead, the
module offering the API is available as the result of a functor which takes as
parameter a module implementing the basic POST method (of module type
Bitcoin.HTTPCLIENT). This module must also define the monad under
which the API calls are wrapped. Should no actual monad be required, then the
identity monad can be declared, and thus users of the API need not be burdened
by having to "live inside the monad".
For convenience sake, OCaml-bitcoin ships with two concrete implementations
of Bitcoin.HTTPCLIENT. The module Bitcoin_ocamlnet is based
on OCamlnet's
Http_client, whereas Bitcoin_ocsigen makes use of Ocsigen's Ocsigen_http_client module. Note
that this latter implementation uses the Lwt monad.
As for keeping track of connections, the usual solution is to have a
function that creates a new connection handle, and have this handle be a
mandatory parameter to any subsequent calls. This is not the solution used by
OCaml-bitcoin. Instead, there are two different mechanisms by which you can
configure the connection. First, since the module offering the API is already
created via a functor, it makes sense to use this same mechanism to also
indicate the connection endpoint. Obligingly, the functor that creates the API
module actually takes two parameters: the previously described
Bitcoin.HTTPCLIENT, and a Bitcoin.CONNECTION declaring a
single value default of type conn_t option which if set
defines the default connection. Second, each call accepts an optional parameter
conn containing the connection endpoint information. If present, this
parameter overrides any default connection, and is mandatory if no default
connection was provided upon the functor invocation.
To conclude, note that the test directory contains OUnit-based unit tests. The tests are
not comprehensive — the nature of the Bitcoin network requires a fairly long
wait before one can be certain a transaction did occur as intended — but do
cover a fair amount of important functionality. Obviously, the tests expect to
be run using Bitcoin's Testnet, and will abort on startup if they find
themselves being used on the main network. Just make sure you have at least a
half-dozen coins on your Testnet balance, as these will be sent around (but
back towards your wallet; you may lose some change due to fees, though). You
can obtain Testnet coins for free from the faucet.