Curso
Todo el mundo habla ahora de criptomonedas, en gran parte por la fiebre de Bitcoin. Más interesante que debatir si hay o no una burbuja es entender cómo funciona realmente esta tecnología y qué posibilidades tiene. La historia de Bitcoin empezó en 2008 con un whitepaper titulado "Bitcoin: A Peer-to-Peer Electronic Cash System". En ese documento, el autor bajo el seudónimo Satoshi Nakamoto (todavía hay un gran debate sobre quién es realmente Satoshi) presenta una tecnología e idea revolucionarias: una moneda electrónica descentralizada que funciona sobre algo llamado blockchain. Desde entonces, la idea se ha extendido y hoy se aplica a muchos otros ámbitos.
Yo conocí por primera vez las blockchains en una reunión de la BlockchainSociety en Oxford. Allí todo el mundo estaba entusiasmado con el potencial de esta nueva tecnología. Y no es para menos: una base de datos descentralizada e incorruptible de transacciones monetarias, contratos o lo que se te ocurra (por ejemplo, máquinas de votación imposibles de hackear). La promesa de la blockchain para la comunidad cripto es que transformará industrias enteras al redefinir la confianza, de modo que ya no necesitaremos terceros como bancos o abogados: bastará con el poder de la criptografía.
Aunque la idea básica es bastante intuitiva, entender cómo funcionan las blockchains a nivel técnico es un poco más complejo. La semana pasada me crucé con un artículo en R-bloggers, donde BigData Doc construye una blockchain íntegramente en R. Montarla en R quizá no sea lo más eficiente ni práctico del mundo, pero es una forma estupenda de comprender los principios de programación y criptografía que hay detrás. Yo también quería entenderlo, así que implementé una versión más pequeña de la blockchain en R: "si puedes programarla, es que de verdad la entiendes".
¿Qué es una blockchain?
Imagina que quieres almacenar datos de forma segura. Para ello, primero guardas los datos en un contenedor, al que llamamos bloque. En el caso de Bitcoin, cada bloque contiene varias transacciones financieras. Cuando hay nuevas transacciones (o nuevos datos), se crea un bloque nuevo y se añade a los anteriores para formar una cadena: la blockchain.
Veamos ahora cómo las blockchains usan la criptografía para ser prácticamente imposibles de hackear.
1. Bloques
block_example <- list(index = 1,
timestamp = "2018-01-05 17.00 MST",
data = "some data",
previous_hash = 0,
proof = 9,
new_hash = NULL)
Antes de empezar a construir la blockchain —es decir, a encadenar distintos contenedores de datos— debes conocer dos conceptos más: el hashing y los algoritmos de prueba de trabajo (Proof of Work).
2. Hash
Un hash ayuda a garantizar la integridad de un bloque al conectarlo con los demás bloques de la cadena. Una función hash toma algo como entrada y te devuelve una salida cifrada única. Por ejemplo: le planteas a tu amiga el acertijo «¿Cuál es el mejor programa de estadística: Stata o R?» y le das el hash de la respuesta correcta: "71ec0b920622cf4358bbc21d6a8b41f903584808db53ec07a8aa79119304ce86". Ahora ella puede comprobar por sí misma si ha acertado introduciendo su respuesta en la función hash (en tu caso, el algoritmo SHA256):
library("digest")
digest("Stata" ,"sha256") # primer intento
## [1] "3ac273f00d52dc9caf89cbd71e73e5915229a588117ca3441630089409ddb7bc"
digest("R", "sha256") # segundo intento
## [1] "71ec0b920622cf4358bbc21d6a8b41f903584808db53ec07a8aa79119304ce86"
¿Cómo te ayuda esto?
En este caso, no solo introduces en la función hash la información del bloque (índice, marca temporal, datos), sino también el hash del bloque anterior. Esto significa que solo puedes calcular un hash válido si conoces el del bloque previo, que a su vez se calculó con el del bloque anterior, y así sucesivamente. El resultado es una cadena de bloques inmutable y secuencial. Si alterases un bloque a posteriori, tendrías que recalcular todos los hashes de los bloques siguientes.
# Función que crea el hash de un "bloque"
hash_block <- function(block){
block$new_hash <- digest(c(block$index,
block$timestamp,
block$data,
block$previous_hash), "sha256")
return(block)
}
3. Prueba de trabajo
Si hay mucha información que almacenar en la blockchain, tendrás que crear muchos bloques nuevos. En muchos casos, querrás controlar cuántos bloques se crean. En las criptomonedas, por ejemplo, las monedas perderían valor si se pudieran crear infinitas monedas cada segundo.
Por eso añadimos un algoritmo de "Proof of Work" (PoW) que regula la dificultad de crear un bloque nuevo. La "prueba" demuestra que el ordenador ha realizado una cierta cantidad de trabajo. En la práctica, el objetivo es definir una tarea difícil de generar pero fácil de verificar. En mi caso usaré esta "tarea" como PoW: encontrar el siguiente número divisible por 99 y divisible por el número de prueba del último bloque.
### Algoritmo sencillo de prueba de trabajo
proof_of_work <- function(last_proof){
proof <- last_proof + 1
# Incrementa la prueba hasta encontrar un número divisible por 99 y por la prueba del bloque anterior
while (!(proof %% 99 == 0 & proof %% last_proof == 0 )){
proof <- proof + 1
}
return(proof)
}
En blockchains como Bitcoin o Ethereum, el trabajo de crear nuevos bloques lo hacen los llamados mineros. Cuando hay que crear un bloque, se envía un problema computacional a la red. El minero que resuelve primero el problema de PoW crea el nuevo bloque y recibe una recompensa en Bitcoins (así es como se generan nuevos Bitcoins). Esta "lotería" para encontrar la prueba correcta garantiza que el poder de crear bloques esté descentralizado. Cuando se mina un bloque nuevo, se distribuye a todo el mundo para que cada nodo de la red tenga una copia de la última blockchain. La idea de que la cadena más larga de la red (aquella en la que se ha "invertido más trabajo") es la versión válida se conoce como "consenso descentralizado".
En el caso de Bitcoin, el PoW consiste en encontrar números que generen hashes con un cierto número de ceros iniciales (la mejor explicación que encontré es este vídeo de Savjee). Para adaptarse al aumento de la potencia de cálculo y a la variación en el número de mineros, la dificultad del PoW se ajusta de forma que el tiempo de creación de un bloque se mantenga en torno a diez minutos.
4. Añadir bloques nuevos
Ya sabes cómo es un bloque, cómo se encadenan mediante hashes y cómo se regula el ritmo de creación con PoW. Ahora vamos a juntarlo todo en una función:
# Función que toma el bloque anterior y normalmente algunos datos (en nuestro caso, una cadena que indica qué bloque es)
gen_new_block <- function(previous_block){
# Proof of Work
new_proof <- proof_of_work(previous_block$proof)
# Crear nuevo bloque
new_block <- list(index = previous_block$index + 1,
timestamp = Sys.time(),
data = paste0("this is block ", previous_block$index +1),
previous_hash = previous_block$new_hash,
proof = new_proof)
# Hashear el nuevo bloque
new_block_hashed <- hash_block(new_block)
return(new_block_hashed)
}
Antes de construir tu blockchain, tienes que empezar la cadena en algún punto. Para ello se usa el llamado bloque Génesis. No contiene datos y tiene valores arbitrarios para la prueba y el hash previo (porque no existe un bloque anterior).
# Definir el bloque Génesis (índice 1 y hash previo arbitrario)
block_genesis <- list(index = 1,
timestamp = Sys.time(),
data = "Genesis Block",
previous_hash = "0",
proof = 1)
5. Construir la blockchain
Ahora ya puedes empezar a construir la blockchain. Comienzas con el bloque Génesis y luego añades unos cuantos bloques con un bucle.
blockchain <- list(block_genesis)
previous_block <- blockchain[[1]]
# Cuántos bloques añadimos a la cadena después del Génesis
num_of_blocks_to_add <- 5
# Añadir bloques a la cadena
for (i in 1: num_of_blocks_to_add){
block_to_add <- gen_new_block(previous_block)
blockchain[i+1] <- list(block_to_add)
previous_block <- block_to_add
print(cat(paste0("Block ", block_to_add$index, " has been added", "\n",
"\t", "Proof: ", block_to_add$proof, "\n",
"\t", "Hash: ", block_to_add$new_hash)))
}
## Block 2 has been added
## Proof: 99
## Hash: 7d3dfbb58b410838769f6080dbc62a44a4c5d411a41048c4e597d26dccd1cd38NULL
## Block 3 has been added
## Proof: 198
## Hash: 4f8bdd79d751f9e9829c14c52a737f257285b61e54b29531dd59bf1a530f1097NULL
## Block 4 has been added
## Proof: 396
## Hash: 512b877c4ff92605d9fe10ac73ced20f748742964f306c211c4691f15425a26eNULL
## Block 5 has been added
## Proof: 792
## Hash: a3baaa025186c5bcb2238a888bc65e705ffe73c17dc5c8f26ee337fd62867993NULL
## Block 6 has been added
## Proof: 1584
## Hash: d12c3f54c14f3287a9f31ab542271197ba6a658cee561a9289819dd563fe4991NULL
Si quieres añadir muchos más bloques, verás que tarda cada vez más. La razón es que el número de prueba crece de forma exponencial.

Para criptomonedas como Bitcoin esto sería un problema, ya que el tiempo de creación de un nuevo bloque debe mantenerse más o menos constante (alrededor de 10 minutos en el caso de Bitcoin). Por eso la dificultad del PoW se ajusta continuamente para tener en cuenta el aumento de la potencia de cálculo y la variación en el número de mineros conectados en cada momento.
Por último, así es como se ve un bloque de tu cadena:
blockchain[[5]]
## $index
## [1] 5
##
## $timestamp
## [1] "2018-02-08 12:02:56 GMT"
##
## $data
## [1] "this is block 5"
##
## $previous_hash
## [1] "26cdc16a4560df5fa2fd521dbca22670e2475c35d3dd90781872bee98a164eef"
##
## $proof
## [1] 792
##
## $new_hash
## [1] "2eef25bf0bc4ee81e8c7cd1dfda65855b4ba32aba218d8c525a03a72b3454d74"
Conclusión
En esta breve entrada has creado la blockchain más pequeña posible. El objetivo principal era mostrar cómo es una blockchain e introducir algunos de sus conceptos clave. Entender esta aplicación magistral de la criptografía explica por qué tanta gente se entusiasma con las posibilidades de la blockchain.
Para llevar una blockchain a producción hace falta mucho más trabajo: crear una API, monederos, firmas digitales con pares de claves pública-privada, etc. También solo he rozado la superficie del concepto de consenso descentralizado, que está en el corazón de cualquier red blockchain.
Esta pequeña introducción se inspira en el post de Gerald Nash, que implementó la "tiniest blockchain" en Python. Yo la implementé en R y añadí la prueba de trabajo de Daniel van Flymen.
Para profundizar más en el tema de las blockchains, te recomiendo el brillante y original whitepaper de Bitcoin de Satoshi Nakamoto y el artículo de BigData Doc.
Si tienes comentarios o quieres responder a este post, escríbeme en Twitter: me encontrarás en @jj_mllr o echa un vistazo a @CorrelAid, una red de jóvenes analistas de datos que quiere cambiar el mundo con un enfoque más inclusivo, integrado e innovador del análisis de datos.

