Una moneda es un registro compartido

Una criptomoneda empieza con un registro de quién puede gastar qué. Definimos las reglas de DCoin, comparamos topologías de red y presentamos las herramientas criptográficas que permiten comprobar mensajes sin confiar en quien los envía. Distinguimos autorización de acuerdo, y seudonimato de privacidad.

Actualizado 8 min de lectura

Imaginemos que un grupo de amigos quiere una moneda para intercambiar cosas: un libro, unos apuntes, una tarde de ayuda con un proyecto. La llamaremos DCoin y usaremos Ð como símbolo. Para empezar bastaría con una hoja de cálculo: alguien crea una columna de nombres, asigna saldos y actualiza las filas cada vez que hay un pago.

La hoja ya contiene buena parte de un sistema de pagos. Registra la propiedad y permite que un administrador honrado impida gastar el mismo saldo dos veces. Su debilidad también es evidente: quien la controla puede alterar un saldo, rechazar un pago, perder el archivo o entregar versiones distintas a personas distintas.

Podríamos nombrar a un segundo administrador, añadir copias de seguridad y exigir firmas para los cambios. Son soluciones razonables. Pero probemos otra condición: ningún participante tendrá la última palabra por el mero hecho de administrar el registro. Cualquiera debe poder comprobar las reglas por sí mismo.

Esa condición convierte un pequeño ejercicio de contabilidad en un problema de sistemas distribuidos. Antes de elegir una cadena de bloques, conviene entender qué tareas debe cumplir y qué herramientas tenemos para ello.

1.1 #Qué debe garantizar el registro

Una moneda de este sistema no es un archivo diminuto que viaja de un ordenador a otro: los archivos se copian fácilmente. El registro recoge permisos para gastar cantidades, y un pago modifica esos permisos siguiendo reglas públicas.

DCoin necesita responder a cinco preguntas:

  1. Emisión: ¿de dónde salen las unidades iniciales y cuándo pueden crearse otras nuevas?
  2. Autorización: ¿qué prueba permite gastar una cantidad existente?
  3. Conservación: ¿cómo comprobamos que un pago no gasta más de lo que tiene disponible?
  4. Orden: ¿qué ocurre si dos pagos, admisibles por separado, gastan el mismo dinero?
  5. Replicación: ¿cómo obtienen y verifican los participantes el historial sin recurrir a un único servidor privilegiado?

Son preguntas relacionadas, pero no intercambiables. Una firma puede resolver la autorización sin resolver el orden. Una red puede entregar perfectamente dos mensajes incompatibles. Una base de datos puede conservar con la misma fidelidad un historial válido y otro inválido.

Concretaremos estas diferencias a lo largo de la serie. Por ahora, supongamos que DCoin tiene una asignación inicial publicada y reglas de validación deterministas. Dos ordenadores que reciben el mismo historial válido deben obtener el mismo estado de fondos disponibles. Esto delimita el problema: dejando a un lado errores de implementación, los desacuerdos provienen de datos, historiales o reglas diferentes, y no de un juicio personal del validador.

El entorno difícil es aquel en el que los participantes pueden llegar tarde, desconectarse, mentir o crear muchas identidades. Los mensajes tardan en propagarse. Un nodo puede retener un pago o mostrarlo solo a una parte de la red. La corrección del protocolo no debería depender de que todos reciban todo en el mismo instante.

1.2 #Compartir los datos sin nombrar a su dueño

Una red entre pares permite intercambiar datos directamente. Un nodo puede pedir un bloque a un vecino y servírselo a otro. No hace falta que todos estén conectados con todos: una malla completa de nn participantes necesitaría n(n−1)/2n(n-1)/2 conexiones, algo que pronto resulta poco práctico.

Estas tres estructuras ilustran dependencias distintas. Los ordenadores representan nodos; las líneas, vías de comunicación, no poder de voto ni propiedad.

NodocentralNodosregionalesMalladepares
Figura 1.1. Un nodo central, una jerarquía de nodos y una malla con varias rutas entre pares. Distribuir las conexiones y distribuir la autoridad son decisiones diferentes.

El nodo central es sencillo de operar, pero perderlo interrumpe la comunicación. Los nodos regionales reparten la carga y conservan dependencias de máquinas concretas. Una malla ofrece rutas alternativas, aunque su conectividad depende de qué nodos fallen y de cómo se hayan elegido los vecinos.

Los sistemas reales combinan estos patrones. Un nodo puede descubrir inicialmente a otros mediante unos pocos servicios conocidos y después intercambiar datos sin que cada petición pase por ellos. Ese arranque introduce una dependencia que merece estudiarse, pero es una cuestión distinta de quién valida un pago. Del mismo modo, una red superpuesta estructurada que organiza búsquedas por claves no es lo mismo que una red con nodos centrales.

La replicación tiene un coste. Cada validador completo adicional debe obtener y procesar los datos relevantes; añadirlo no acelera por sí solo un registro replicado globalmente. Los nodos también difieren en ancho de banda, disponibilidad, almacenamiento e influencia sobre la propagación. Decir que siguen las mismas reglas de validación es bastante más preciso que decir que todos son iguales.

En DCoin usaremos una malla para distribuir transacciones y bloques candidatos. Un nodo es una fuente de datos, no de verdad. Siempre que pueda, quien recibe los datos comprobará su contenido.

1.3 #Obtener la huella de un mensaje con un hash

Una función hash criptográfica transforma una secuencia de bytes de cualquier longitud en un resultado de longitud fija. SHA-256, por ejemplo, produce 256 bits. Su representación hexadecimal tiene 64 caracteres porque cada dígito hexadecimal representa cuatro bits.

Nos interesan tres propiedades prácticas: que sea inviable encontrar una entrada para una salida dada; encontrar otra entrada con el mismo hash que un mensaje concreto; o encontrar cualquier pareja de entradas distintas con el mismo hash. Son expectativas computacionales, no una afirmación de que las colisiones no existen. Hay infinitos mensajes y solo un número finito de resúmenes.

Hello,friendsSHA-256Resumen5326d882e6c7...Cambiarunbytecambialahuella
Figura 1.2. Los mismos bytes producen siempre el mismo resumen. El valor mostrado son los primeros 12 caracteres hexadecimales de SHA-256, no el hash completo. Conservamos el mensaje en inglés para poder contrastarlo con el código.

Podemos comprobar la figura con la biblioteca estándar de Python:

from hashlib import sha256
 
for message in ("Hello, friends", "Hello, friends!"):
    print(sha256(message.encode("utf-8")).hexdigest())

Los resultados son:

5326d882e6c7a07e3727f52ad6f47b30158a06efc3fdc543adb3b629b6490ae6
c56846234054fb1fd7f36474fbf6c3c1a41667f473d6ba3f21a02c798c5c211f

Añadir un solo signo de exclamación cambia por completo el resumen. Por eso un hash sirve para detectar cambios y referirse de forma compacta a objetos grandes. No oculta la entrada. Quien sospeche que el mensaje era «Hello, friends» puede calcular su hash y compararlo. Aplicar un hash a un nombre o una dirección de correo no proporciona, por sí solo, privacidad.

Hay otro detalle que debemos explicitar: los hashes operan sobre bytes. Dos objetos JSON con el mismo significado pueden tener espacios u órdenes de claves distintos y, por tanto, hashes diferentes. DCoin debe definir una serialización inequívoca antes de utilizar un resumen como identificador de transacción.

1.4 #Autorizar un pago con una firma

Los hashes identifican contenido, pero no quién lo aprobó. Si cualquiera puede calcular H(m)H(m), cualquiera puede adjuntarlo a un pago falsificado.

Un esquema de firma digital introduce un par de claves. La privada permanece en poder de su titular; la pública puede distribuirse. El titular firma un mensaje con la clave privada. Quien lo verifica comprueba el mensaje y la firma mediante la clave pública. Un esquema adecuado hace inviable producir una firma válida para un mensaje nuevo sin conocer la clave privada.

FirmaMensajemClaveprivadaFirmarMensaje¯rmadoVeri¯caci¶onmy¾ClavepublicaVeri¯carValida/invalida
Figura 1.3. Para firmar hacen falta el mensaje y la clave privada. Para verificar, el mensaje, su firma y la clave pública. El mensaje permanece legible durante todo el proceso.

En DCoin, un pago debe comprometer las entradas que gasta, los destinatarios y las cantidades del modo previsto por las reglas. Firmar un mensaje incompleto es peligroso: si el destinatario no queda cubierto, alguien podría sustituirlo sin invalidar la firma. Las reglas reales de firma de transacciones son más complejas que «firmar el hash de la transacción». Lo esencial es especificar exactamente qué bytes y qué contexto de gasto se autorizan.

Una firma válida indica que la clave correspondiente autorizó ese mensaje. No demuestra que la clave pertenezca a una persona concreta, que esa persona quisiera ejecutar la acción ni que su dispositivo no estuviera comprometido. Tampoco demuestra que el dinero siga disponible: un mismo titular puede firmar dos pagos incompatibles.

Por eso las firmas no cifran identidades. Un registro público puede revelar cantidades, vínculos entre transacciones y patrones de actividad aunque sus claves no estén asociadas a nombres legales. Seudonimato y privacidad son propiedades distintas; DCoin no obtiene la segunda por el mero hecho de usar criptografía.

1.5 #Falta un historial común

Ya podemos distribuir mensajes, detectar cambios y comprobar autorizaciones. Supongamos que Alice tiene 500 Ð. Firma un pago a Bob y otro a Carol que gastan esos mismos fondos. Ambas firmas son válidas. Ambos mensajes pueden llegar a nodos honrados. Ni una función hash mejor ni más conexiones nos dicen cuál debe ejecutarse.

Un administrador único resolvería el conflicto ordenando los pagos en su base de datos. Nuestro diseño necesita una alternativa que los participantes puedan verificar y aplicar aunque al principio reciban mensajes diferentes.

Ese es el objetivo del resto de la serie. Primero necesitamos un modelo preciso de salida disponible, transacción y bloque. Después podremos comparar historiales rivales. La cadena de bloques solo es útil si sus reglas convierten un conjunto de mensajes firmados en un registro coherente de lo que puede gastarse a continuación.

La formulación original del doble gasto y su solución mediante prueba de trabajo están en el artículo de Bitcoin. DCoin es un modelo didáctico; cuando pasemos a los formatos reales de Bitcoin, indicaremos expresamente esa frontera.