Para despejar un poco la cabeza este fin de semana, me he puesto a leer cosas que no tengan absolutamente nada que ver con mi día a día. Buceando en una de esas listas de correo de criptografía que sigo por pura afición, me crucé con un invento bastante peculiar que un tal Satoshi Nakamoto publicó a principios de enero. Lo llama Bitcoin y lo define como un sistema de dinero electrónico completamente P2P.
A ver, sistemas de intercambio P2P tenemos a patadas (la mula, BitTorrent...), y ya estamos más que acostumbrados a dejarnos el PC encendido toda la noche bajando isos de distribuciones Linux a la velocidad máxima que nos permite nuestra humilde conexión. Pero esto es distinto. Aquí no se comparten archivos enteros, se comparten "monedas" criptográficas y, lo más curioso de todo, se utiliza la potencia bruta del procesador de tu máquina para generar un consenso distribuido en la red y validar las transacciones.
Me ha picado muchísimo la curiosidad, me he bajado el código fuente directamente desde SourceForge y he estado echándole un ojo a las tripas del asunto. Está escrito en C++ y viene bastante limpio, preparado para compilar tanto con Visual Studio en Windows como con GCC si andas trasteando en alguna distribución de Linux (yo lo he compilado en mi viejo portátil con Ubuntu 8.10 sin demasiados dolores de cabeza).
Almacenamiento local: Tirando de clásicos
A nivel arquitectónico, me ha sorprendido gratamente la elección para el almacenamiento local. En lugar de complicarse la vida programando un motor de almacenamiento propio desde cero o usar una base de datos relacional pesada que consuma recursos en balde, el cliente de Bitcoin utiliza Berkeley DB (BDB), la mítica librería embebida que todos hemos sufrido o disfrutado alguna vez.
Lo que hace este software es empaquetar cada transacción de la red en un bloque, y cada bloque se enlaza con el anterior calculando un hash criptográfico SHA-256. Así van formando una cadena ininterrumpida (lo que en el código fuente llaman block chain). Si miras las tripas, la inicialización de la base de datos tira directamente de la API pura de BDB para persistir los índices en un archivo binario llamado blkindex.dat.
// Fragmento simplificado del código de inicialización de BDB en 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);
Básicamente, levanta un entorno transaccional seguro en el directorio de datos del usuario (que por defecto en un Windows XP se te va a la ruta oculta C:\Documents and Settings\Usuario\Datos de programa\Bitcoin) y crea un árbol B para indexar rápidamente por dónde va el bloque válido más largo. Es una solución elegante para evitar corrupciones masivas si el programa se cuelga abruptamente. Y creédme, pasa; mi procesador se quedó completamente tieso una vez al poner la CPU al 100% generando hashes de validación.
Descubrimiento de pares a la vieja escuela
Otra cosa que me ha parecido una auténtica genialidad (y un poco chapuza a la vez) es cómo descubren los nodos unos a otros en internet sin un rastreador central. El programa incluye internamente un cliente de IRC. Sí, como lo oyes. Cuando arrancas el ejecutable, se conecta silenciosamente a un canal de IRC específico para publicar tu IP e ir leyendo las direcciones del resto de usuarios que están en el canal. Así es como descubre a sus pares iniciales para empezar a sincronizar la famosa base de datos de bloques por el puerto 8333. Muy ingenioso y muy de la vieja escuela.
¿Un futuro viable?
No sé qué recorrido real tendrá este experimento a la larga. Conceptualmente es brillante cómo resuelve el problema del doble gasto sin necesitar un banco o servidor central validando operaciones. Es una idea muy parecida a lo que usa el sistema Hashcash para frenar el spam exigiendo cálculo computacional en los servidores de correo, pero llevado a un extremo descentralizado.
Pero seamos realistas: por diseño, la base de datos BDB tiene que guardarse entera, con toda la historia de todas las transacciones de todo el mundo, en el disco de cada nodo que participe en la red. Ahora mismo, un par de meses después de que Nakamoto generara el primer bloque génesis, la cadena entera ocupa unos pocos megas. ¿Pero qué pasará si este invento lo empiezan a usar miles de personas para enviarse dinero a diario? En tres o cuatro años mi disco SATA de 500GB se llenaría exclusivamente de bloques de texto críptico. Sinceramente, no veo que esa arquitectura sea escalable a nivel global sin devorar completamente el ancho de banda y la capacidad de almacenamiento de las máquinas domésticas.
En fin, como ejercicio de diseño distribuido me ha encantado la lectura del código. Voy a dejar el cliente corriendo en segundo plano este fin de semana a ver si mi máquina consigue "minar" alguno de estos bitcoins, aunque sólo sea por ver en directo cómo va creciendo el dichoso archivo blkindex.dat.
Si alguno más le está dando un tiento al código de esta red P2P, que deje un comentario y compartimos impresiones o parches.