To clear my head a bit this weekend, I've started reading things that have absolutely nothing to do with my day-to-day work. Diving into one of those cryptography mailing lists that I follow purely out of hobby, I came across a rather peculiar invention that a certain Satoshi Nakamoto published in early January. He calls it Bitcoin and defines it as a completely P2P electronic cash system.

Let's see, we have plenty of P2P file sharing systems (the mule, BitTorrent...), and we are more than used to leaving the PC on all night downloading Linux distribution ISOs at the maximum speed that our humble connection allows. But this is different. Here you do not share entire files, you share cryptographic "coins" and, most curious of all, you use the raw power of your machine's processor to generate a distributed consensus on the network and validate transactions.

It has piqued my curiosity a lot, I have downloaded the source code directly from SourceForge and I have been taking a look at its guts. It is written in C++ and comes quite clean, ready to compile both with Visual Studio on Windows and with GCC if you are tinkering with some Linux distribution (I compiled it on my old laptop with Ubuntu 8.10 without too many headaches).

Local storage: Pulling from classics

At an architectural level, I was pleasantly surprised by the choice for local storage. Instead of complicating their lives by programming their own storage engine from scratch or using a heavy relational database that consumes resources in vain, the Bitcoin client uses Berkeley DB (BDB), the legendary embedded library that we have all suffered from or enjoyed at some point.

What this software does is pack each network transaction into a block, and each block is linked to the previous one by calculating a SHA-256 cryptographic hash. This is how they form an uninterrupted chain (what they call a block chain in the source code). If you look under the hood, the database initialization calls the pure BDB API directly to persist the indices in a binary file called blkindex.dat.

// Simplified fragment of the BDB initialization code in main.cpp (Bitcoin v0.1)
DBEnv dbenv(0);
dbenv.open(GetDataDir().c_str(),
           DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN | DB_THREAD | DB_RECOVER,
           S_IRUSR | S_IWUSR);

DB db(&dbenv, 0);
db.open(NULL, "blkindex.dat", NULL, DB_BTREE, DB_CREATE | DB_THREAD, 0);

Basically, it spins up a secure transactional environment in the user's data directory (which by default on Windows XP goes to the hidden path C:\Documents and Settings\Usuario\Datos de programa\Bitcoin) and creates a B-tree to quickly index the longest valid block path. It is an elegant solution to avoid massive corruption if the program crashes abruptly. And believe me, it happens; my processor completely froze once when pushing the CPU to 100% generating validation hashes.

Old-school peer discovery

Another thing that seemed like pure genius to me (and a bit of a hack at the same time) is how nodes discover each other on the internet without a central tracker. The program internally includes an IRC client. Yes, you heard that right. When you launch the executable, it silently connects to a specific IRC channel to publish your IP and read the addresses of the rest of the users who are in the channel. This is how it discovers its initial peers to start synchronizing the famous block database over port 8333. Very ingenious and very old school.

A viable future?

I don't know what real trajectory this experiment will have in the long run. Conceptually it is brilliant how it solves the double-spending problem without needing a central bank or server validating operations. It is a very similar idea to what the Hashcash system uses to stop spam by demanding computational calculation on mail servers, but taken to a decentralized extreme.

But let's be realistic: by design, the BDB database must be saved in its entirety, with the entire history of all transactions from everyone in the world, on the disk of each node participating in the network. Right now, a couple of months after Nakamoto generated the first genesis block, the entire chain takes up a few megabytes. But what will happen if thousands of people start using this invention to send money to each other on a daily basis? In three or four years my 500GB SATA disk would be filled exclusively with cryptic text blocks. Honestly, I don't see how that architecture is scalable globally without completely devouring the bandwidth and storage capacity of home machines.

Anyway, as a distributed design exercise I loved reading the code. I am going to leave the client running in the background this weekend to see if my machine manages to "mine" any of these bitcoins, if only to see live how the darn blkindex.dat file grows.

If anyone else is giving the code of this P2P network a try, leave a comment and let's share impressions or patches.