La Tecnología Blockchain
Podemos decir que blockchain es la tecnología del bitcoin y otras criptomonedas, pero éstas son sólo una parte de todo el espectro que abarca tanto el concepto como la tecnología.
La tecnología realmente tiene sus orígenes en 1991, cuando Stuart Haber y W. Scott Stornetta describieron el primer proceso sobre una cadena de bloques asegurados criptográficamente, más adelante, en 2008 se empezó a ser popular con la llegada del bitcoin y hoy en día la demanda de esta tecnología esta abarcando otros escenarios como las aplicaciones comerciales, lo cual predice un crecimiento anual del 51% para el 2022 en varios mercados, como el sector financiero y el internet de las cosas (IoT) entre otros de acuerdo con publicaciones de MarketWatch.
En 2008, un artículo titulado Bitcoin: un sistema de dinero electrónico peer-to-peer fue publicado por Satoshi Nakamoto. El artículo describe la combinación de técnicas criptográficas y de una red peer-to-peer sin necesidad de confiar en una autoridad centralizada (como lo hacen los bancos) para realizar pagos de una persona a otra.
El mismo artículo introduce un sistema distribuido para almacenar información (ahora llamado “blockchain”), que tiene un campo de aplicación mucho más amplio que únicamente pagos o criptomonedas.
Desde entonces, el interés por el blockchain ha crecido prácticamente en todos los sectores. Por lo que Blockchain es ahora la tecnología debajo de las criptomonedas completamente digitales como Bitcoin, tecnologías de computación distribuida como Ethereum, y frameworks de código abierto como Hyperledger Fabric, sobre el cual está montada la IBM Blockchain Platform.
El término Blockchain hace referencia a una cadena de bloques que establecen un registro único, consensuado y distribuido en varios nodos de una red. Para el caso de las criptomonedas, podría decirse que es la bitacora contable donde se registran todas las transacciones. Es decir, en cada bloque se almacena:
- Una cantidad de registros o transacciones válidas
- Información referente a ese bloque
- Su vinculación con el bloque anterior y el bloque siguiente
Cada bloque tiene un identificador único del tipo hash que representa la huella digital del bloque.
En este sentido, cada bloque tiene un lugar específico e inamovible dentro de la cadena, ya que en cada bloque existe información del hash del bloque anterior, y el propio ligado al posterior.
La cadena completa se guarda en cada nodo de la red que conforma el blockchain, se almacena una copia exacta de la cadena en todos los nodos participantes de la red.
A medida que se crean nuevas transacciones o registros, estos son verificados y validados por los nodos de la red y posteriormente añadidos a un nuevo bloque que se enlaza a la cadena.
Dado que es una tecnología distribuida donde cada nodo de la red almacena una copia exacta de la cadena, la disponibilidad de la información esta garantizada en todo momento. Si un nodo de la red sufre averías o ataques, la información esta disponible en los demás nodos.
La integridad de la información también está asegurada dado que al ser un registro consensuado, todos los nodos contienen la misma información y para alterar la información sería necesario que se modificara en la cadena completa o en al menos el 51% de los nodos.
Al mismo tiempo, dado que cada bloque esta vinculado al bloque siguiente, una vez que se agrega uno nuevo a la cadena, el mismo se vuelve inalterable, si un bloque se modificara, su relación con la cadena se rompe, por lo tanto, toda la información registrada en los bloques es inmutable y perpetua.
En este sentido, blockchain permite almacenar información que jamás se podrá perder, modificar o eliminar.
En cada nodo de la red se utilizan certificados y firmas digitales para verificar la información y validar las transacciones, así como los datos almacenados en la cadena, permitiendo así, asegurar la autenticidad de la información.
Usos de Blockchain
Blockchain puede ser utilizado para certificar y validad cualquier tipo de información, así como almacenar documentos importantes, como escrituras sin depender de terceros.
En general, cualquier tipo de información que necesite ser preservada de forma intacta y que deba permanecer disponible de manera segura, descentralizada y más económica que a través de intermediarios. Si dicha información se guarda cifrada se puede garantizar su confidencialidad ya que sólo quienes cuenten con la llave de cifrado podrán acceder a ella.
Sector salud
Los registros de salud podrían estar unificados y almacenado en blockchain para que el historial médico de los pacientes se mantenga seguro y al mismo tiempo disponible para cada médico autorizado, independientemente del servicio de salud.
La industria farmacéutica podría utilizar blockchain para validar y verificar medicamentos y con ello evitar falsificaciones.
Internet de las Cosas (IoT)
El reto para blockchain recae en los millones de dispositivos conectados a Internet dado que el modelo centralizado no va a soportar la cantidad de dispositivos que cada vez va en aumento. Con blockchain los dispositivos pueden comunicarse a través de la red de manera segura, directa y confiable, sin intermediarios.
Como se ha mencionado anteriormente, Blockchain permite verificar, validar, rastrear y almacenar todo tipo de información, desde certificados digitales, servicios de logística y mensajería, contratos inteligentes, dinero, transacciones financieras, así como sistemas de elecciones democráticas, entre otros.
The Blockchain Council
El Consejo Blockchain (Blockchain Council) es un grupo autorizado de expertos y entusiastas cuya labor es promover la investigación, el desarrollo y evangelizar sobre los casos de uso, productos y conocimientos relacionados con la tecnología Blockchain para lograr un mundo mejor.
La tecnología Blockchain está surgiendo rápidamente con un amplio alcance en el futuro.
Blockchain actúa como una red financiera, un software, un libro mayor distribuido, etc. Debido a esta gran variedad de beneficios y características, las empresas ahora están cambiando su sistema de trabajo centralizado y tradicional a esta tecnología futurista.
El consejo de Blockchain crea un entorno y crea conciencia entre las empresas, los desarrolladores y la sociedad al educarlos en los temas de Blockchain.
Programación para Blockchain
El blockchain council tiene varios cursos y certificaciones interesantes para desarrollar aplicaciones para blockchain, incluso hay tutoriales para desarrollar e implementar un blockchain público desde cero con una aplicación simple para desplegarlo.
Crear puntos de acceso para diferentes funciones del blockchain, como agregar una transacción utilizando el microframework Flask, ejecutar los programas en múltiples máquinas para crear una red descentralizada. En los ejemplos se presenta también el desarrollo de una interfaz de usuario para interactuar con el blockchain y almacenar información para cualquier uso como pagos, peer-to-peer, conversaciones, comercio electrónico, etc.
Blockchain con Python
En este ejemplo e crea un blockchain público gestionado por la aplicación nodo_servidor y se almacena información en formato JSON
{ "author": "nombre_del_autor", "content": "Información que el autor quiere compartir", "timestamp": "El tiempo en el que el contenido fue creado" }
nodo_servidor.py
from hashlib import sha256 | |
import json | |
import time | |
from flask import Flask, request | |
import requests | |
class Block: | |
def __init__(self, index, transactions, timestamp, previous_hash): | |
self.index = index | |
self.transactions = transactions | |
self.timestamp = timestamp | |
self.previous_hash = previous_hash | |
self.nonce = 0 | |
def compute_hash(self): | |
""" | |
A function that return the hash of the block contents. | |
""" | |
block_string = json.dumps(self.__dict__, sort_keys=True) | |
return sha256(block_string.encode()).hexdigest() | |
class Blockchain: | |
# difficulty of our PoW algorithm | |
difficulty = 2 | |
def __init__(self): | |
self.unconfirmed_transactions = [] | |
self.chain = [] | |
self.create_genesis_block() | |
def create_genesis_block(self): | |
""" | |
A function to generate genesis block and appends it to | |
the chain. The block has index 0, previous_hash as 0, and | |
a valid hash. | |
""" | |
genesis_block = Block(0, [], time.time(), "0") | |
genesis_block.hash = genesis_block.compute_hash() | |
self.chain.append(genesis_block) | |
@property | |
def last_block(self): | |
return self.chain[–1] | |
def add_block(self, block, proof): | |
""" | |
A function that adds the block to the chain after verification. | |
Verification includes: | |
* Checking if the proof is valid. | |
* The previous_hash referred in the block and the hash of latest block | |
in the chain match. | |
""" | |
previous_hash = self.last_block.hash | |
if previous_hash != block.previous_hash: | |
return False | |
if not Blockchain.is_valid_proof(block, proof): | |
return False | |
block.hash = proof | |
self.chain.append(block) | |
return True | |
def proof_of_work(self, block): | |
""" | |
Function that tries different values of nonce to get a hash | |
that satisfies our difficulty criteria. | |
""" | |
block.nonce = 0 | |
computed_hash = block.compute_hash() | |
while not computed_hash.startswith('0' * Blockchain.difficulty): | |
block.nonce += 1 | |
computed_hash = block.compute_hash() | |
return computed_hash | |
def add_new_transaction(self, transaction): | |
self.unconfirmed_transactions.append(transaction) | |
@classmethod | |
def is_valid_proof(cls, block, block_hash): | |
""" | |
Check if block_hash is valid hash of block and satisfies | |
the difficulty criteria. | |
""" | |
return (block_hash.startswith('0' * Blockchain.difficulty) and | |
block_hash == block.compute_hash()) | |
@classmethod | |
def check_chain_validity(cls, chain): | |
result = True | |
previous_hash = "0" | |
for block in chain: | |
block_hash = block.hash | |
# remove the hash field to recompute the hash again | |
# using `compute_hash` method. | |
delattr(block, "hash") | |
if not cls.is_valid_proof(block, block.hash) or \ | |
previous_hash != block.previous_hash: | |
result = False | |
break | |
block.hash, previous_hash = block_hash, block_hash | |
return result | |
def mine(self): | |
""" | |
This function serves as an interface to add the pending | |
transactions to the blockchain by adding them to the block | |
and figuring out Proof Of Work. | |
""" | |
if not self.unconfirmed_transactions: | |
return False | |
last_block = self.last_block | |
new_block = Block(index=last_block.index + 1, | |
transactions=self.unconfirmed_transactions, | |
timestamp=time.time(), | |
previous_hash=last_block.hash) | |
proof = self.proof_of_work(new_block) | |
self.add_block(new_block, proof) | |
self.unconfirmed_transactions = [] | |
# announce it to the network | |
announce_new_block(new_block) | |
return new_block.index | |
app = Flask(__name__) | |
# the node's copy of blockchain | |
blockchain = Blockchain() | |
# the address to other participating members of the network | |
peers = set() | |
# endpoint to submit a new transaction. This will be used by | |
# our application to add new data (posts) to the blockchain | |
@app.route('/new_transaction', methods=['POST']) | |
def new_transaction(): | |
tx_data = request.get_json() | |
required_fields = ["author", "content"] | |
for field in required_fields: | |
if not tx_data.get(field): | |
return "Invlaid transaction data", 404 | |
tx_data["timestamp"] = time.time() | |
blockchain.add_new_transaction(tx_data) | |
return "Success", 201 | |
# endpoint to return the node's copy of the chain. | |
# Our application will be using this endpoint to query | |
# all the posts to display. | |
@app.route('/chain', methods=['GET']) | |
def get_chain(): | |
# make sure we've the longest chain | |
consensus() | |
chain_data = [] | |
for block in blockchain.chain: | |
chain_data.append(block.__dict__) | |
return json.dumps({"length": len(chain_data), | |
"chain": chain_data}) | |
# endpoint to request the node to mine the unconfirmed | |
# transactions (if any). We'll be using it to initiate | |
# a command to mine from our application itself. | |
@app.route('/mine', methods=['GET']) | |
def mine_unconfirmed_transactions(): | |
result = blockchain.mine() | |
if not result: | |
return "No transactions to mine" | |
return "Block #{} is mined.".format(result) | |
# endpoint to add new peers to the network. | |
@app.route('/add_nodes', methods=['POST']) | |
def register_new_peers(): | |
nodes = request.get_json() | |
if not nodes: | |
return "Invalid data", 400 | |
for node in nodes: | |
peers.add(node) | |
return "Success", 201 | |
# endpoint to add a block mined by someone else to | |
# the node's chain. The block is first verified by the node | |
# and then added to the chain. | |
@app.route('/add_block', methods=['POST']) | |
def validate_and_add_block(): | |
block_data = request.get_json() | |
block = Block(block_data["index"], | |
block_data["transactions"], | |
block_data["timestamp", | |
block_data["previous_hash"]]) | |
proof = block_data['hash'] | |
added = blockchain.add_block(block, proof) | |
if not added: | |
return "The block was discarded by the node", 400 | |
return "Block added to the chain", 201 | |
# endpoint to query unconfirmed transactions | |
@app.route('/pending_tx') | |
def get_pending_tx(): | |
return json.dumps(blockchain.unconfirmed_transactions) | |
def consensus(): | |
""" | |
Our simple consnsus algorithm. If a longer valid chain is | |
found, our chain is replaced with it. | |
""" | |
global blockchain | |
longest_chain = None | |
current_len = len(blockchain.chain) | |
for node in peers: | |
response = requests.get('http://{}/chain'.format(node)) | |
length = response.json()['length'] | |
chain = response.json()['chain'] | |
if length > current_len and blockchain.check_chain_validity(chain): | |
current_len = length | |
longest_chain = chain | |
if longest_chain: | |
blockchain = longest_chain | |
return True | |
return False | |
def announce_new_block(block): | |
""" | |
A function to announce to the network once a block has been mined. | |
Other blocks can simply verify the proof of work and add it to their | |
respective chains. | |
""" | |
for peer in peers: | |
url = "http://{}/add_block".format(peer) | |
requests.post(url, data=json.dumps(block.__dict__, sort_keys=True)) | |
app.run(debug=True, port=8000) |
La vista de la aplicación cliente es la siguiente con el archivo view.py
import datetime | |
import json | |
import requests | |
from flask import render_template, redirect, request | |
from app import app | |
# The node with which our application interacts, there can be multiple | |
# such nodes as well. | |
CONNECTED_NODE_ADDRESS = "http://127.0.0.1:8000" | |
posts = [] | |
def fetch_posts(): | |
""" | |
Function to fetch the chain from a blockchain node, parse the | |
data and store it locally. | |
""" | |
get_chain_address = "{}/chain".format(CONNECTED_NODE_ADDRESS) | |
response = requests.get(get_chain_address) | |
if response.status_code == 200: | |
content = [] | |
chain = json.loads(response.content) | |
for block in chain["chain"]: | |
for tx in block["transactions"]: | |
tx["index"] = block["index"] | |
tx["hash"] = block["previous_hash"] | |
content.append(tx) | |
global posts | |
posts = sorted(content, key=lambda k: k['timestamp'], | |
reverse=True) | |
@app.route('/') | |
def index(): | |
fetch_posts() | |
return render_template('index.html', | |
title='YourNet: Decentralized ' | |
'content sharing', | |
posts=posts, | |
node_address=CONNECTED_NODE_ADDRESS, | |
readable_time=timestamp_to_string) | |
@app.route('/submit', methods=['POST']) | |
def submit_textarea(): | |
""" | |
Endpoint to create a new transaction via our application. | |
""" | |
post_content = request.form["content"] | |
author = request.form["author"] | |
post_object = { | |
'author': author, | |
'content': post_content, | |
} | |
# Submit a transaction | |
new_tx_address = "{}/new_transaction".format(CONNECTED_NODE_ADDRESS) | |
requests.post(new_tx_address, | |
json=post_object, | |
headers={'Content-type': 'application/json'}) | |
return redirect('/') | |
def timestamp_to_string(epoch_time): | |
return datetime.datetime.fromtimestamp(epoch_time).strftime('%H:%M') |
Conclusión
Este ejemplo cubre los fundamentos de un blockchain público. Implementa un blockchain desde cero y crea una simple aplicación permitiendo a los usuarios compartir información en él.