Announcing OCaml-bitcoin 1.0
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.