Como crear un Blockchain con JavaScript y NodeJS.
Una cadena de bloques o también conocida como blockchain es una estructura de datos en la que la información se guarda en conjuntos (bloques), a los que se ánade meta informaciones relativas a otro bloque de la cadena anterior en una linea temporal, lo que significa que su contenido solo puede ser editado modificando todos los bloques anteriores.
En este post aprenderemos como crear un blockchain con javascript y nodejs.
Crearemos una carpeta con el nombre de nuestra elección en este caso la llamaremos “blockchain” , dentro de ella crearemos un archivo que se llamara main.js.
Ahora abriremos esta carpeta con el editor de código de nuestra preferencia.
Bien ahora empecemos con el código!!
1.- Primero crearemos una clase llamada Block el cual contendrá una función constructor, también crearemos las funciones calculateHash, mineBlock, la función constructor creara las instancias de los objetos del bloque y les proporcionara sus propiedades.
class Block {
constructor(data) {
this.index = 0;
this.date = new Date();
this.data = data;
this.previousHash = "0";
this.hash = this.calculateHash();
this.nonce = 0;
}
calculateHash() {
}
mineBlock(difficulty) {
}
2.- Iniciaremos npm, abriremos el terminal y nos ubicamos en nuestro proyecto ahora solo ejecutaremos en siguiente comando y solo resta configurar el proyecto a nuestro gusto.
npm init
3.- Ahora aremos uso de un modulo de npm llamado crypto-js, este puede ser instalado con el siguiente comando.
npm install –save crypto-js
4.- Ahora que la biblioteca esta instalada crearemos una constante llamada SHA265 que requiere de crypto-js/sha265, esto lo usaremos para crear la función de calculo.
const SHA256 = require('crypto-js/sha256');
class Block {
constructor(data) {
this.index = 0;
this.date = new Date();
this.data = data;
this.previousHash = "0";
this.hash = this.calculateHash();
this.nonce = 0;
}
calculateHash() {
return SHA256(this.index + this.previousHash + this.date + this.data + this.nonce).toString();
}
mineBlock(difficulty) {
while(!this.hash.startsWith(difficulty)) {
this.nonce++;
this.hash = this.calculateHash();
}
}
}
La función calculateHash la usaremos para dar a cada bloque su propio hash, este toma cada pieza del objeto Block, lo lanza en una función SHA256 y lo convierte a una cadena.
La segunda función mineBlock sera usada para procesar con seguridad las transacciones en redes blockchain agregando dificultad al proceso de generado del hash, en este caso la dificulta sera el numero de ceros con el cual comenzara el hash.
5.- Ahora que creamos la estructura de nuestro bloque individual, necesitamos crear una estructura un objeto de clase Blockchain esta tendrá las siguientes funciones, constructor, createGenesis, latestBlock, addBlock, checkValid.
- Nuestra clase Blockchain necesita tener la capacidad de crear instancias, de iniciar, acceder a la información mas reciente del bloque y ampliarse agregando un nuevo bloque.
class Blockchain {
constructor(difficulty = '00') {
this.chain = [this.createGenesis()];
this.difficulty = difficulty;
}
createGenesis() {
return new Block(0, {amount: 100});
}
latestBlock() {
return this.chain[this.chain.length - 1];
}
addBlock(newBlock) {
newBlock.index = this.latestBlock().index + 1;
newBlock.previousHash = this.latestBlock().hash;
newBlock.hash = newBlock.calculateHash();
newBlock.mineBlock(this.difficulty);
console.log('Minado!! '+ newBlock.hash+' con nonce '+ newBlock.nonce);
this.chain.push(newBlock);
}
checkValid() {
for (let i = 1; i < this.chain.length; i++) {
const currentBlock = this.chain[i];
const previousBlock = this.chain[i - 1];
if (currentBlock.hash !== currentBlock.calculateHash()) {
return false;
}
if (currentBlock.previousHash !== previousBlock.hash) {
return false;
}
}
return true;
}
}
Bien expliquemos que hicimos en este código.
Función Constructor.
- Esta función crea una instancia en nuestra cadena de bloques con una propiedad en una estructura de lista, por eso nuestro objeto Block tiene índices esta propiedad se utiliza para encontrar su posición en nuestra lista de cadenas, además define la dificultad de minado inicial.
- Esta función crea una instancia en nuestra cadena de bloques con una propiedad en una estructura de lista, por eso nuestro objeto Block tiene índices esta propiedad se utiliza para encontrar su posición en nuestra lista de cadenas, además define la dificultad de minado inicial.
Función createGenesis.
- Nuestra cadena de bloques necesita la función createGenesis ya que esta crea el primer bloque de nuestra cadena. Por lo general en blockchain el primer bloque de cualquier se conoce como “Bloque de Génesis” , por eso el nombre de createGenesis, normalmente la información del bloque génesis es introducido manualmente. Como es el primer bloque de la cadena su índice sera 0, la fecha y hora serán los actuales, en cuanto al hash anterior sera 0 ya que no hay otro hash que lo proceda.
- Nuestra cadena de bloques necesita la función createGenesis ya que esta crea el primer bloque de nuestra cadena. Por lo general en blockchain el primer bloque de cualquier se conoce como “Bloque de Génesis” , por eso el nombre de createGenesis, normalmente la información del bloque génesis es introducido manualmente. Como es el primer bloque de la cadena su índice sera 0, la fecha y hora serán los actuales, en cuanto al hash anterior sera 0 ya que no hay otro hash que lo proceda.
Función latestBlock.
- Esta función obtiene la información del bloque mas reciente y también sera necesaria en la siguiente función.
- Esta función obtiene la información del bloque mas reciente y también sera necesaria en la siguiente función.
Función addBlock.
- Para que nuestro bloque tenga la capacidad de extenderse continuamente necesita esta función, las cadenas de bloque tienen esta funcionalidad, la mas conocida es la del Bitcoin (BTC) esta se encarga de crear bloques nuevos cada 10 minutos con la información de las transacciones realizadas en se marco de tiempo.
Su implementación de la función addBlock es sencilla esta toma el objeto Block como una entrada la cual posee una marca de tiempo y datos. Luego, nuestra función addBlock usara la función latestBlock para darla un índice y un hash anterior a nuestro nuevo bloque, después de eso le damos su propio hash usando la función calculateHash, también pasaremos la dificulta de minado definida en la propiedad difficulty, y finalmente empujamos este bloque en nuestra cadena, ahora tenemos un nuevo bloque.
- Para que nuestro bloque tenga la capacidad de extenderse continuamente necesita esta función, las cadenas de bloque tienen esta funcionalidad, la mas conocida es la del Bitcoin (BTC) esta se encarga de crear bloques nuevos cada 10 minutos con la información de las transacciones realizadas en se marco de tiempo.
Función checkValid.
- Esta función verifica la integridad de la cadena de bloques y detecta si algo ha sido manipulado.
Debes saber que los hashes son críticos para detectar cambios en nuestra cadena ya que incluso el cambio mas pequeño en un objeto resultara en un hash completamente diferente, por lo tanto esta función usa un bucle for para recorrer la cadena e intentar coincidir sus hashes para detectar cambios.
Hay 2 partes en nuestro bucle la primera es hacer coincidir currentBlock.hash con currentBlock.calculateHash y la segundo es hacer coincidir currentBlock.previousHash con previousBlock.hash, el primero se usa para verificar si la información de currentBlock ha sido manipulada sin actualizar currentBlock.hash. El segundo se usa para verificar si un bloque anterior ha sido modificado.
- Esta función verifica la integridad de la cadena de bloques y detecta si algo ha sido manipulado.
6.- Finalmente agregaremos esta lineas al final de nuestro código que añaden dos bloques con datos, los validara y mostraran en consola.
let myCoin = new Blockchain('000');
myCoin.addBlock(new Block({amount: 50}));
myCoin.addBlock(new Block({amount: 25}));
console.log("La cadena de bloques es valida?", myCoin.checkValid());
Nota: La clase Blockchain recibe la dificulta de minado en este caso la dificulta son 3 ceros, entre mas ceros mas difícil sera el minado de los bloques.
7.- Ahora nuestro código final se vera así.
const SHA256 = require('crypto-js/sha256');
class Block {
constructor(data) {
this.index = 0;
this.date = new Date();
this.data = data;
this.previousHash = "0";
this.hash = this.calculateHash();
this.nonce = 0;
}
calculateHash() {
return SHA256(this.index + this.previousHash + this.date + this.data + this.nonce).toString();
}
mineBlock(difficulty) {
while(!this.hash.startsWith(difficulty)) {
this.nonce++;
this.hash = this.calculateHash();
}
}
}
class Blockchain {
constructor(difficulty = '00') {
this.chain = [this.createGenesis()];
this.difficulty = difficulty;
}
createGenesis() {
return new Block(0, {amount: 100});
}
latestBlock() {
return this.chain[this.chain.length - 1];
}
addBlock(newBlock) {
newBlock.index = this.latestBlock().index + 1;
newBlock.previousHash = this.latestBlock().hash;
newBlock.hash = newBlock.calculateHash();
newBlock.mineBlock(this.difficulty);
console.log('Minado!! '+ newBlock.hash+' con nonce '+ newBlock.nonce);
this.chain.push(newBlock);
}
checkValid() {
for (let i = 1; i < this.chain.length; i++) {
const currentBlock = this.chain[i];
const previousBlock = this.chain[i - 1];
if (currentBlock.hash !== currentBlock.calculateHash()) {
return false;
}
if (currentBlock.previousHash !== previousBlock.hash) {
return false;
}
}
return true;
}
}
let myCoin = new Blockchain('0000');
myCoin.addBlock(new Block({amount: 50}));
myCoin.addBlock(new Block({amount: 25}));
console.log("La cadena de bloques es valida?", myCoin.checkValid());
8.- Ahora solo queda probar nuestro blockchain abre el terminal, ubícate en la raíz de tu proyecto y ejecuta el siguiente comando.
node main.js
9.- Veras algo como esto.
Minado!! 000020f23e31c8f28fb54adb6754edd4319cb74065663acce78981630077028e con nonce 130611
Minado!! 000052c92a3c0533f6379bbca7f3096a4aa5cba6b7280761f983284a5680ca8f con nonce 23024
La cadena de bloques es valida? true
10.- Para ver la informacion que contiene cada bloque agrega al final la siguiente linea de código.
console.log(JSON.stringify(myCoin, null, 4));
- Ahora deberías ver algo como esto.
Minado!! 000004d09ad97f858e05c4b101fce77ae3670f908f820dca5fa5d882f3e284d7 con nonce 63331
Minado!! 0000b78e1ea385c3d39f83b4d4bf22f53fd675e8b21a4a33afb4ba0d799d34af con nonce 9669
La cadena de bloques es valida? true
{
"chain": [
{
"index": 0,
"date": "2018-10-16T23:41:01.033Z",
"data": 0,
"previousHash": "0",
"hash": "3b2403dfac8d26ae556adb59f97b6f925d41687e3c436b0d70e09d99d31bf733",
"nonce": 0
},
{
"index": 1,
"date": "2018-10-16T23:41:01.038Z",
"data": {
"amount": 50
},
"previousHash": "3b2403dfac8d26ae556adb59f97b6f925d41687e3c436b0d70e09d99d31bf733",
"hash": "000004d09ad97f858e05c4b101fce77ae3670f908f820dca5fa5d882f3e284d7",
"nonce": 63331
},
{
"index": 2,
"date": "2018-10-16T23:41:07.385Z",
"data": {
"amount": 25
},
"previousHash": "000004d09ad97f858e05c4b101fce77ae3670f908f820dca5fa5d882f3e284d7",
"hash": "0000b78e1ea385c3d39f83b4d4bf22f53fd675e8b21a4a33afb4ba0d799d34af",
"nonce": 9669
}
],
"difficulty": "0000"
}
Listo ahora ya has creado una cadena de bloques (Blockchain) en javascript y nodejs, en futuros post aprenderemos mas sobre blockchain y javascript.
El repositorio de todo el código: GitHub