Construyendo el Blockchain mas pequeño con Python 3.6!

blockchain

Algunos ya piensan que Blockchain es la solución a todos los problemas y no cabe duda de que esta nueva tecnología es una maravilla de la informática Pero, ¿qué es exactamente una cadena de bloques?

Blockchain un libro digital de contabilidad en el que las transacciones realizadas en bitcoin u otra criptomoneda se registran cronológica y públicamente. En términos más generales, es una base de datos pública donde los datos nuevos se almacenan en un contenedor llamado bloque y se agregan a una cadena inmutable (por lo tanto, cadena de bloques) con datos agregados en el pasado. En el caso de Bitcoin y otras criptomonedas, estos datos son grupos de transacciones. Pero, por supuesto, los datos pueden ser de cualquier tipo.

La tecnología Blockchain ha dado lugar a nuevas monedas totalmente digitales como Bitcoin y Litecoin que no son emitidas ni administradas por una autoridad central. Esto brinda una nueva libertad a las personas que creen que los sistemas bancarios actuales son una estafa o están sujetos a fallas.

Blockchain también ha revolucionado la informática distribuida en forma de tecnologías como Ethereum, que ha introducido conceptos interesantes como contratos inteligentes.

En este artículo, haré una cadena de bloques simple en menos de 50 líneas de código Python 3.6 que se llamará TanoChainCoin (THC).

Comenzaremos por definir primero cómo serán nuestros bloques. En blockchain, cada bloque se almacena con una marca de tiempo y, opcionalmente, un índice. En TanoChainCoin vamos a almacenar ambos. Y para ayudar a garantizar la integridad en todo el blockchain, cada bloque tendrá un hash autoidentificado. Al igual que Bitcoin, el hash de cada bloque será un hash criptográfico del índice del bloque, la marca de tiempo (timestamp), los datos y el hash del hash del bloque anterior. Ah, y los datos pueden ser lo que quieras.

Primero importamos las librerias que necesitamos:

import hashlib as hasher
import datetime as date

Y vamos a construir la primera clase: “Block”:

 

class Block:
    def __init__(self, index, timestamp, data, previous_hash):
        self.index = str(index).encode()
        self.timestamp = str(timestamp).encode()
        self.data = data.encode()
        self.previous_hash = previous_hash.encode()
        self.hash = self.hash_block()

    def hash_block(self):
        sha = hasher.sha256()
        sha.update(self.index)
        sha.update(self.timestamp)
        sha.update(self.data)
        sha.update(self.previous_hash)
        return sha.hexdigest()

La Clase necesita de el numero de indice (index), la hora del sistema (timestamp), los datos que vamos a ingresar a la cadena (data) y finalmente el hash del bloque anterior (previous_hash) como para poder encadenar ambos bloques.

En la funcion “hash_block” se almacena un hash random de 256 bits en la variable sha y luego va sumando los valores del bloque como el numero de indice (index), el timestamp, etc..  usando del  metodo update() como parametro. Esto va actualizando el hash.

Lo mismo se repite con el resto de los parametros hasta retornar el hash final (sha.hexdigest()) que incluye, como dijimos, el index, el timestamp, los datos y el hash del bloque anterior.

Listo. Tenemos nuestra estructura de bloques, pero estamos creando una cadena de bloques.

Necesitamos comenzar a agregar bloques a la cadena real. Como mencioné anteriormente, cada bloque requiere información del bloque anterior. Pero con eso dicho, surge una pregunta: ¿cómo llega el primer bloque en la cadena de bloques?

Bueno, el primer bloque, o bloque de genesis, es un bloque especial. En muchos casos, se agrega manualmente o tiene una lógica única que permite que se agregue. Creamos una función que simplemente devuelve un bloque de genesis para facilitar las cosas. Este bloque es del índice 0 y tiene un valor de datos arbitrario y un valor arbitrario en el parámetro “previous_hash“.

def create_genesis_block():
        # Construimos un bloque manualmente con indice 0 y un hash anterior aleatorio.
        return Block(0, date.datetime.now(), "Genesis Block", "0")

Ahora que somos capaces de crear un bloque de génesis, necesitamos una función que genere bloques sucesivos en la cadena de bloques. Esta función tomará el bloque anterior en la cadena como parámetro, creará los datos para el bloque que se generará y devolverá el nuevo bloque con sus datos apropiados.

Cuando la información de hash de bloques nuevos de bloques anteriores, la integridad de la cadena de bloques aumenta con cada bloque nuevo. Si no hiciéramos esto, sería más fácil para un tercero “cambiar el pasado” y reemplazar nuestra cadena por una completamente nueva. Esta cadena de valores hash actúa como prueba criptográfica y ayuda a garantizar que una vez que se agrega un bloque a la cadena de bloques, no se puede reemplazar ni eliminar:

def next_block(last_block):
        this_index = int(last_block.index) + 1
        this_timestamp = date.datetime.now()
        this_data = "Hey! Soy un bloque! " + str(this_index)
        this_hash = last_block.hash
        return Block(int(this_index), this_timestamp, this_data, this_hash)

 

Esa es la mayoría del trabajo dificil. Ahora,  ya podemos crear la cadena de bloques.

En nuestro caso, el blockchain en sí es una simple lista de Python. El primer elemento de la lista es el bloque de génesis. Y, por supuesto, tenemos que agregar los bloques siguientes. Debido a que THC es la cadena de bloques más pequeña, solo agregaremos 20 bloques nuevos. Podemos hacer esto con un ciclo for.

# Crea el Blockchain y agrega el bloque genesis.
blockchain = [create_genesis_block()]
previous_block = blockchain[0]

# Cuantos bloques se agregaran a la cadena despues del bloque de genesis
num_of_blocks_to_add = 20

# Loop para agregar los bloques a la cadena
for i in range(0, num_of_blocks_to_add):
  block_to_add = next_block(previous_block)
  blockchain.append(block_to_add)
  previous_block = block_to_add
  # Corran la bola! XD
  print("El bloque #{} se ha agregado al blockchain!".format(block_to_add.index))
  print("Hash: {}\n".format(block_to_add.hash))

 

Vamos a desglosar un poco esto.

Primero creamos la cadena de bloques “Blockchain” como una lista cuyo primer elemento debe ser el bloque genesis. Llamando a la funcion create_genesis_block() se instancia un objeto en la clase Block() que retorna un primer bloque con indice 0. Esto retorna el  hash del primer elemento o “bloque genesis” de la lista que conforma nuestra cadena (Blockchain) y es almacenado en la variable previous_block

num_of_blocks_to_add define la cantidad de bloques que vamos a encadenar.

Comenzando a iterar, sobre un rango de 0 hasta el numero de bloques que definimos en la variable num_of_blocks_to_add, se almacenara en la variable block_to_add la salida de la funcion next_block incluyendo el parametro previous_block que, si recapitulamos, no es mas que el hash del bloque de genesis, ya que se trata del primer elemento instanciado en la lista con indice 0.

La funcion next_block va a introducir los datos del bloque nuevo. Para eso toma el valor del indice del bloque anterior (0 – genesis) llamando a next_block.index  y le suma 1 para crear el indice del bloque actual, con la libreria date conseguimos el timestamp de este nuevo bloque. Los datos que contendra son texto que agregamos manualmente (“Hey! Soy un bloque””) y por ultimo, va a almacenar en la variable “this_hash” el hash del bloque anterior, en este caso del bloque genesis.

Con toda esa informacion al final de la funcion next_block() ya retornamos un objeto que instanciado previamente en la clase Block() generara el nuevo hash con los datos que creamos en next_block y el hash del bloque genesis generando asi el primer encadenamiento entre el bloque genesis y el bloque 1.

Ahora resta sumarlo a la cadena. Para eso usamos el metodo .append() para sumar este nuevo bloque a la lista o “Blockchain”.

Para poder continuar el loop tenemos que redefinir la variable previous_block por el nuevo valor de “block_to_add” que en este caso pasa a ser el bloque 1.

Imprimimos el numero de indice de la lista o bloque que se ha sumado a la cadena y el hash correspondiente al mismo para volver a llamar a la funcion “next
_block” y repetir el proceso tantas veces como el numero que definimos en num_of_blocks_to_add.

Aca va el codigo funcional completo para Python3.6:

import hashlib as hasher
import datetime as date


class Block:
    def __init__(self, index, timestamp, data, previous_hash):
        self.index = str(index).encode()
        self.timestamp = str(timestamp).encode()
        self.data = data.encode()
        self.previous_hash = previous_hash.encode()
        self.hash = self.hash_block()

    def hash_block(self):
        sha = hasher.sha256()
        sha.update(self.index)
        sha.update(self.timestamp)
        sha.update(self.data)
        sha.update(self.previous_hash)
        return sha.hexdigest()

def create_genesis_block():
        # Construimos un bloque manualmente con indice 0 y un hash anterior aleatorio.
        return Block(0, date.datetime.now(), "Genesis Block", "0")

def next_block(last_block):
        this_index = int(last_block.index) + 1
        this_timestamp = date.datetime.now()
        this_data = "Hey! Soy un bloque! " + str(this_index)
        this_hash = last_block.hash
        return Block(int(this_index), this_timestamp, this_data, this_hash)


# Crea el Blockchain y agrega el bloque genesis.
blockchain = [create_genesis_block()]
previous_block = blockchain[0]

# Cuantos bloques se agregaran a la cadena despues del bloque de genesis
num_of_blocks_to_add = 20

# Loop para agregar los bloques a la cadena
for i in range(0, num_of_blocks_to_add):
  block_to_add = next_block(previous_block)
  blockchain.append(block_to_add)
  previous_block = block_to_add
  # Tell everyone about it!
  print("El bloque #{} se ha agregado al blockchain!".format(block_to_add.index))
  print("Hash: {}\n".format(block_to_add.hash))

 

Si lo corremos deberian ver una salida similar a esta:

Screen Shot 2018-02-18 at 4.22.05 PM

Ahi podemos ver que luego de crearse el bloque genesis, siguiendo el analisis anterior ese primer hash es el resultado de los datos del bloque 1 sumados al bloque genesis, el segundo hash sera entonces el resultado de los elementos del bloque 2 sumados al previo hash del bloque genesis con el bloque 1 y asi sucesivamente.

Pronto estare portando la segunda parte.

Nota: En este trabajo es una adaptacion del genial articulo de Gerald Nash (https://medium.com/crypto-currently/lets-build-the-tiniest-blockchain-e70965a248b), traducido al Espanol, portado a Python 3.6 y con un analisis extra en la logica del codigo.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s