#STEM empresa enfocada en resolver objetivos de negocio a través de la tecnología y el desarrollo de productos #blockchain #bigdata #smartproduct #iot

Tintoreros 4, 11170 Medina Sidonia, España
cadifornia@cadifornia.cc

Acceso Holded
Acceso Synology
Acceso Admin
Acceso Webmail

Cadifornia

Programa Blockchain = Entiende Blockchain

El concepto básico de blockchain es bastante simple: una base de datos distribuida que mantiene una lista de registros ordenados en continuo crecimiento. Sin embargo, es fácil confundirse, ya que cuando hablamos de cadenas de bloques también hablamos de los problemas que estamos tratando de resolver con ellos.

Este es el caso de los populares proyectos basados en cadenas de bloques como Bitcoin y Ethereum . El término “cadena de bloques” suele estar fuertemente ligado a conceptos como transacciones, contratos inteligentes.

Esto hace que la comprensión de las cadenas de bloques resulte complejo(más de lo que debería ser). Aquí os dejamos una blockchain que implementamos, super sencilla, en JavaScript llamada CadiChain.

Estructura de bloques

El primer paso lógico es decidir la estructura de bloques. Para mantener las cosas lo más simples posible, incluimos sólo lo más necesario: índice, marca de tiempo, datos, hash y hash anterior.

class Block {
    constructor(index, previousHash, timestamp, data, hash) {
        this.index = index;
        this.previousHash = previousHash.toString();
        this.timestamp = timestamp;
        this.data = data;
        this.hash = hash.toString();
    }
}
Bloque de hash

El bloque necesita ser “triturado” para mantener la integridad de los datos. Un SHA-256 se hace cargo del contenido del bloque. Cabe señalar que este hash no tiene nada que ver con la “minería”, ya que no hay problema que resolver.

var calculateHash = (index, previousHash, timestamp, data) => {
    return CryptoJS.SHA256(index + previousHash + timestamp + data).toString();
};
Generando un bloque

Para generar un bloque debemos conocer el hash del bloque anterior y crear el resto del contenido necesario (= índice, hash, datos y timestamp). Los datos de bloqueo son proporcionados por el usuario final.

var generateNextBlock = (blockData) => {
    var previousBlock = getLatestBlock();
    var nextIndex = previousBlock.index + 1;
    var nextTimestamp = new Date().getTime() / 1000;
    var nextHash = calculateHash(nextIndex, previousBlock.hash, nextTimestamp, blockData);
    return new Block(nextIndex, previousBlock.hash, nextTimestamp, blockData, nextHash);
};
Almacenamiento de los bloques

Vamos a utrilizar una matriz para almacenar el blockchain. El primer bloque de la cadena de bloques es se debe generar “manual” y es llamado comunmente “bloque genesis”.

var getGenesisBlock = () => {
    return new Block(0, "0", 1465154705, "BLOQUE GENESIS", "816534932c2b7154836da6afc367695e6337db8a921823784c14378abed4f7d7");
};

var blockchain = [getGenesisBlock()];
Validación de la integridad de los bloques

Llega el momento en el que debemos de ser capaces de validar si un bloque o una cadena de bloques son válidos en términos de integridad. Esto es especialmente importante a tener en cuenta cuando recibimos nuevos bloques de otros nodos y debemos decidir si los aceptamos o no.

var isValidNewBlock = (newBlock, previousBlock) => {
    if (previousBlock.index + 1 !== newBlock.index) {
        console.log('invalid index');
        return false;
    } else if (previousBlock.hash !== newBlock.previousHash) {
        console.log('invalid previoushash');
        return false;
    } else if (calculateHashForBlock(newBlock) !== newBlock.hash) {
        console.log('invalid hash: ' + calculateHashForBlock(newBlock) + ' ' + newBlock.hash);
        return false;
    }
    return true;
};
Resolver conflictos (Elegir la cadena más larga)

Siempre debe haber un solo conjunto explícito de bloques en la cadena en un momento dado. En caso de conflictos (por ejemplo, dos nodos generan el bloque número 72) elegimos la cadena que tenga el mayor número de bloques.

var replaceChain = (newBlocks) => {
    if (isValidChain(newBlocks) && newBlocks.length > blockchain.length) {
        console.log('Received blockchain is valid. Replacing current blockchain with received blockchain');
        blockchain = newBlocks;
        broadcast(responseLatestMsg());
    } else {
        console.log('Received blockchain invalid');
    }
};
Comunicación con otros nodos

Una parte esencial de un nodo es compartir y sincronizar la cadena de bloques con otros nodos. Las siguientes reglas se utilizan para mantener la red sincronizada.

  • Cuando un nodo genera un nuevo bloque, lo transmite a la red
  • Si un nodo se conecta a un nuevo par, busca el último bloque
  • O cuando un nodo se encuentra con un bloque que tiene un índice mayor que el bloque actual conocido, agrega el bloque a su cadena actual o consulta por el bloque completo.

No se utiliza la detección automática por pares. La ubicación (=URLs) de los pares debe añadirse manualmente.

Control del nodo

El usuario debe ser capaz de controlar el nodo de alguna manera. Esto se hace configurando un servidor HTTP.

var initHttpServer = () => {
    var app = express();
    app.use(bodyParser.json());

    app.get('/blocks', (req, res) => res.send(JSON.stringify(blockchain)));
    app.post('/mineBlock', (req, res) => {
        var newBlock = generateNextBlock(req.body.data);
        addBlock(newBlock);
        broadcast(responseLatestMsg());
        console.log('block added: ' + JSON.stringify(newBlock));
        res.send();
    });
    app.get('/peers', (req, res) => {
        res.send(sockets.map(s => s._socket.remoteAddress + ':' + s._socket.remotePort));
    });
    app.post('/addPeer', (req, res) => {
        connectToPeers([req.body.peer]);
        res.send();
    });
    app.listen(http_port, () => console.log('Listening http on port: ' + http_port));
};

Como se ha visto, el usuario puede interactuar con el nodo de las siguientes maneras:

  • Listar todos los bloques
  • Crear un nuevo bloque con un contenido dado por el usuario
  • Enumerar o agregar pares

 

La forma más sencilla de controlar el nodo es, por ejemplo, con Curl:

#get all blocks from the node
curl http://localhost:3001/blocks
Arquitectura

Debe tenerse en cuenta que el nodo realmente expone dos servidores web: Uno para que el usuario controle el nodo (servidor HTTP) y otro para la comunicación peer-to-peer entre los nodos (servidor HTTP Websocket).

Conlusiones

La CadiChain ha sido creada con fines de demostración y aprendizaje. Al no disponer de un algoritmo de “minería”, no puede ser utilizado en una red pública. No obstante, implementa las características básicas para una cadena de bloque funcional.

Cadifornia



cadifornia@cadifornia.cc
Centro Avanzado de Desarrollo e Innovación.