Cómo construir una cadena de bloques de criptomonedas simple en Node.js
Publicado: 2022-03-10smashingCoin
, utilizando los conceptos de clases de JavaScript y Node.js. Pruébelo, ¡es más simple de lo que piensa!El auge sin precedentes de las criptomonedas y la tecnología de cadena de bloques que las sustenta han arrasado en todo el mundo, desde sus humildes comienzos como concepto académico hace más de una década hasta la actual adopción cada vez mayor en diversas industrias.
La tecnología blockchain está recibiendo mucha atención debido a su capacidad para mejorar la seguridad en entornos sin confianza, aplicar la descentralización y hacer que los procesos sean eficientes.
Tradicionalmente, Python ha sido el lenguaje de programación de facto para el desarrollo de blockchain. Sin embargo, con la proliferación de esta asombrosa tecnología, las opciones de desarrollo también han aumentado, y Node.js no se ha quedado atrás.
En este tutorial, voy a hablar sobre cómo crear una cadena de bloques de criptomonedas simple en Node.js. No va a ser demasiado elegante, pero lo suficiente como para ayudarlo a comprender cómo funciona una cadena de bloques.
Llamaré a esta simple criptomoneda smashingCoin
.
Si usted es un desarrollador de JavaScript que quiere dar un salto al floreciente campo de las criptomonedas, este artículo lo equipará con las habilidades necesarias para comenzar. O, si tiene curiosidad acerca de cómo funcionan las cosas en el mundo de las criptomonedas, este tutorial puede ayudarlo a responder algunas de sus preguntas.
Lectura recomendada : Comprender la integridad de los subrecursos por Drew McLellan
requisitos previos
Para seguir este tutorial con éxito, necesitará tener lo siguiente:
- Node.js instalado en su máquina. Puedes descargarlo desde aquí;
- Un editor de código, como Visual Studio Code, Sublime Text o cualquier otro.
Empecemos…
¿Qué es una cadena de bloques?
Blockchain es la tecnología que impulsa las monedas digitales, como Bitcoin y Ethereum. Es una innovadora tecnología de registro público distribuido que mantiene una lista de registros en continuo crecimiento, denominada bloques, que se conectan de forma segura mediante criptografía.
El término blockchain se ganó su nombre por la forma en que guarda los datos de las transacciones, es decir, en bloques que se conectan entre sí para crear una cadena . El tamaño de la cadena de bloques crece con el aumento del número de transacciones realizadas.
Cualquier dato de transacción válido se registra en la red blockchain, que se rige por las reglas de igual a igual que estipulan los participantes. Por ejemplo, estos datos podrían contener el "valor" del bloque, como en monedas digitales, un registro de transacciones (como cuando las partes intercambian bienes y servicios) o privilegios de derechos, como cuando la cadena registra información de propiedad.
Además de los datos de la transacción, cada bloque puede contener su propio hash criptográfico (un identificador único o huella digital), su propio valor de nonce (un número aleatorio arbitrario que se usa una vez en los cálculos criptográficos), el hash del bloque anterior y una marca de tiempo reciente. transacciones autenticadas.
Dado que cada nuevo bloque debe apuntar al bloque anterior, si un bloque se incorpora a la cadena sin contener el hash correcto del último bloque, podría invalidar toda la cadena de bloques. Esta propiedad de inmutabilidad es clave para la seguridad de las cadenas de bloques.
Además, a menudo se aplican varios tipos de protocolos de consenso para mantener la autenticidad de la cadena de bloques. El consenso garantiza que todos los participantes estén de acuerdo con las transacciones validadas por la red.
Por ejemplo, un protocolo de consenso de uso común es la prueba de trabajo, cuyo objetivo es identificar un número que encuentre una solución a un problema matemático complicado después de completar una determinada cantidad de trabajo informático.
La idea principal del trabajo de prueba es que cualquier participante en la red blockchain debería encontrar este número difícil de identificar pero fácilmente verificable. En consecuencia, desalienta el spam y la manipulación de la estructura de la cadena de bloques.
En el caso de la mayoría de las criptomonedas, agregar un nuevo bloque a la cadena de bloques requiere resolver una ecuación matemática compleja, cuya dificultad aumenta con el tiempo a medida que crece la cadena de bloques. En consecuencia, cualquier persona que demuestre que ha trabajado resolviendo este problema es compensada con una moneda digital, en un proceso denominado “minería”.
Cómo crear un bloque
Ahora, después de presentar la tecnología blockchain y cómo funciona, veamos cómo podemos aplicar los conceptos para crear un bloque. Como se mencionó anteriormente, los bloques son los que se interrelacionan entre sí para formar una cadena de bloques.
Para crear la moneda smashingCoin
, usaré clases de JavaScript, que se introdujeron en ES6.
¿Listo?
Ensuciémonos las manos…
Aquí está el código para la clase CryptoBlock
:
const SHA256 = require('crypto-js/sha256'); class CryptoBlock{ constructor(index, timestamp, data, precedingHash=" "){ this.index = index; this.timestamp = timestamp; this.data = data; this.precedingHash = precedingHash; this.hash = this.computeHash(); } computeHash(){ return SHA256(this.index + this.precedingHash + this.timestamp + JSON.stringify(this.data)).toString(); } }
Como puede ver en el código anterior, creé la clase CryptoBlock
y le agregué el método constructor()
, tal como se hace en cualquier otra clase de JavaScript. Luego, para inicializar sus propiedades, asigné los siguientes parámetros al método constructor
:
index | Es un número único que rastrea la posición de cada bloque en toda la cadena de bloques. |
timestamp | Mantiene un registro de la hora de ocurrencia de cada transacción completada. |
data | Proporciona datos sobre las transacciones completadas, como los detalles del remitente, los detalles del destinatario y la cantidad negociada. |
precedingHash | Apunta al hash del bloque anterior en la cadena de bloques, algo importante para mantener la integridad de la cadena de bloques. |
Además, utilicé el método computeHash
para calcular el hash del bloque en función de sus propiedades, como se indica en los datos anteriores.
Como puede ver, importé la biblioteca de JavaScript crypto-js y usé su módulo crypto-js/sha256
para calcular el hash de cada bloque. Dado que el módulo devuelve un objeto numérico, utilicé el método toString()
para convertirlo en una cadena.
Para agregar la biblioteca crypto-js a su proyecto, vaya a la terminal y ejecute el siguiente comando para instalarlo usando npm
:
npm install --save crypto-js
Después de ejecutar el comando anterior, el directorio de módulos de nodo, que contiene la biblioteca y otros archivos esenciales, se agregará a la carpeta de su proyecto.
Cómo crear una cadena de bloques
Como se explicó anteriormente, la tecnología blockchain se basa en el concepto de que todos los bloques están encadenados entre sí. Entonces, creemos una clase CryptoBlockchain
que será responsable de manejar las operaciones de toda la cadena. Aquí es donde la goma se encontrará con la carretera.
La clase CryptoBlockchain
mantendrá las operaciones de la cadena de bloques utilizando métodos auxiliares que realizan diferentes tareas, como crear nuevos bloques y agregarlos a la cadena.
Aquí está el código para la clase CryptoBlockchain
:
class CryptoBlockchain{ constructor(){ this.blockchain = [this.startGenesisBlock()]; } startGenesisBlock(){ return new CryptoBlock(0, "01/01/2020", "Initial Block in the Chain", "0"); } obtainLatestBlock(){ return this.blockchain[this.blockchain.length - 1]; } addNewBlock(newBlock){ newBlock.precedingHash = this.obtainLatestBlock().hash; newBlock.hash = newBlock.computeHash(); this.blockchain.push(newBlock); } }
Permítanme hablar sobre las funciones de cada uno de los métodos auxiliares que constituyen la clase CryptoBlockchain
.
1. Método del constructor
Este método instancia la cadena de bloques. Dentro del constructor, creé la propiedad blockchain
, que se refiere a una matriz de bloques. Observe que le pasé el método startGenesisBlock()
, que crea el bloque inicial en la cadena.
2. Creación del bloque Génesis
En una cadena de bloques, el bloque de génesis se refiere al primer bloque creado en la red. Siempre que un bloque se integre con el resto de la cadena, debe hacer referencia al bloque anterior.
Por el contrario, en el caso de este bloque inicial, no tiene ningún bloque anterior al que señalar. Por lo tanto, un bloque de génesis generalmente está codificado en la cadena de bloques. De esta manera, se pueden crear bloques posteriores en él. Suele tener un índice de 0.
Usé el método startGenesisBlock()
para crear el bloque de génesis. Tenga en cuenta que lo creé usando la clase CryptoBlock
creada anteriormente y pasé el index
, la timestamp
de tiempo, data
y los parámetros Hash precedingHash
.
3. Obtención del último bloque
Obtener el último bloque en la cadena de bloques ayuda a garantizar que el hash del bloque actual apunte al hash del bloque anterior, manteniendo así la integridad de la cadena.
Usé el método obtainLatestBlock()
para recuperarlo.
4. Agregar nuevos bloques
Usé el método addNewBlock()
para agregar un nuevo bloque a la cadena. Para lograr esto, configuro el hash anterior del nuevo bloque para que sea igual al hash del último bloque de la cadena, lo que garantiza que la cadena sea a prueba de manipulaciones.
Dado que las propiedades del nuevo bloque cambian con cada nuevo cálculo, es importante volver a calcular su hash criptográfico. Después de actualizar su hash, el nuevo bloque se inserta en la matriz de la cadena de bloques.
En realidad, agregar un nuevo bloque a una cadena de bloques no es tan fácil debido a las varias comprobaciones que se han realizado. No obstante, para esta simple criptomoneda, es suficiente para demostrar cómo funciona realmente una cadena de bloques.
Probando la cadena de bloques
Ahora, probemos nuestra cadena de bloques simple y veamos si funciona.
Aquí está el código:
let smashingCoin = new CryptoBlockchain(); smashingCoin.addNewBlock(new CryptoBlock(1, "01/06/2020", {sender: "Iris Ljesnjanin", recipient: "Cosima Mielke", quantity: 50})); smashingCoin.addNewBlock(new CryptoBlock(2, "01/07/2020", {sender: "Vitaly Friedman", recipient: "Ricardo Gimenes", quantity: 100}) ); console.log(JSON.stringify(smashingCoin, null, 4));
Como puede ver en el código anterior, creé una nueva instancia de la clase CryptoBlockchain
y la llamé smashingCoin
. Luego, agregué dos bloques a la cadena de bloques usando algunos valores arbitrarios. En el parámetro data
, utilicé un objeto y agregué los detalles del remitente, los detalles del destinatario y la cantidad negociada.
Si ejecuto el código en la terminal, este es el resultado que obtengo:
¡Así es como se ve smashingCoin
! Es un objeto que contiene la propiedad blockchain
, que es una matriz que contiene todos los bloques de la cadena. Como puede ver en la imagen de arriba, cada bloque hace referencia al hash del bloque anterior. Por ejemplo, el segundo bloque hace referencia al hash del primer bloque. Después de probar y ver que nuestra cadena de bloques funciona, agreguemos algunas funcionalidades más para mejorar las características de smashingCoin
.
Cómo verificar la integridad de la cadena de bloques
Como se mencionó anteriormente, una característica clave de una cadena de bloques es que una vez que se agrega un bloque a la cadena, no se puede cambiar sin invalidar la integridad del resto de la cadena.
Por lo tanto, para verificar la integridad de la cadena de bloques, agregaré un método checkChainValidity()
a la clase CryptoBlockchain
.
Los hashes son fundamentales para garantizar la validez y la seguridad de una cadena de bloques porque cualquier cambio en el contenido de un bloque dará como resultado la producción de un hash completamente nuevo y la invalidación de la cadena de bloques.
Como tal, el método checkChainValidity()
hará uso de declaraciones if
para verificar si el hash de cada bloque ha sido alterado. Comenzando desde el primer bloque creado, recorrerá toda la cadena de bloques y verificará su validez. Tenga en cuenta que dado que el bloque de génesis estaba codificado, no se verificará.
Además, el método verificará si los hash de cada dos bloques consecutivos apuntan entre sí. Si la integridad de la cadena de bloques no se ha visto comprometida, devuelve verdadero; de lo contrario, en caso de anomalías, devuelve falso.
Aquí está el código:
checkChainValidity(){ for(let i = 1; i < this.blockchain.length; i++){ const currentBlock = this.blockchain[i]; const precedingBlock= this.blockchain[i-1]; if(currentBlock.hash !== currentBlock.computeHash()){ return false; } if(currentBlock.precedingHash !== precedingBlock.hash) return false; } return true; }
Cómo agregar una prueba de trabajo
Como se mencionó anteriormente, la prueba de trabajo es el concepto que se aplica para aumentar la dificultad que conlleva minar o agregar nuevos bloques a la cadena de bloques.
En el caso de smashingCoin
, emplearé un algoritmo simple que disuade a las personas de generar nuevos bloques fácilmente o enviar spam a la cadena de bloques.
Entonces, en la clase CryptoBlock
, agregaré otro método llamado proofOfWork().
Esencialmente, este algoritmo simple identifica un número, pasado como una propiedad de difficulty
, de modo que el hash de cada bloque contiene ceros iniciales que corresponden a este nivel de difficulty
.
Asegurar que el hash de cada bloque comience con la cantidad de ceros establecida en el nivel de difficulty
requiere mucha potencia informática. Cuanto mayor sea el nivel de dificultad, más tiempo llevará extraer nuevos bloques.
Además, agregaré un valor nonce
aleatorio a cada bloque hash de modo que, cuando se realice el refrito, se puedan cumplir las restricciones de nivel de dificultad.
Aquí está el código:
proofOfWork(difficulty){ while(this.hash.substring(0, difficulty) !==Array(difficulty + 1).join("0")){ this.nonce++; this.hash = this.computeHash(); } }
Y aquí está el método computeHash()
actualizado con la variable nonce
incluida:
computeHash(){ return SHA256(this.index + this.precedingHash + this.timestamp + JSON.stringify(this.data)+this.nonce).toString(); }
Además, para implementar el mecanismo de prueba de trabajo en la generación de nuevos bloques, lo incluiré en el método addNewBlock()
:
addNewBlock(newBlock){ newBlock.precedingHash = this.obtainLatestBlock().hash; //newBlock.hash = newBlock.computeHash(); newBlock.proofOfWork(this.difficulty); this.blockchain.push(newBlock); }
Terminando
Aquí está el código completo para construir la criptomoneda smashingCoin
usando Node.js:
const SHA256 = require("crypto-js/sha256"); class CryptoBlock { constructor(index, timestamp, data, precedingHash = " ") { this.index = index; this.timestamp = timestamp; this.data = data; this.precedingHash = precedingHash; this.hash = this.computeHash(); this.nonce = 0; } computeHash() { return SHA256( this.index + this.precedingHash + this.timestamp + JSON.stringify(this.data) + this.nonce ).toString(); } proofOfWork(difficulty) { while ( this.hash.substring(0, difficulty) !== Array(difficulty + 1).join("0") ) { this.nonce++; this.hash = this.computeHash(); } } } class CryptoBlockchain { constructor() { this.blockchain = [this.startGenesisBlock()]; this.difficulty = 4; } startGenesisBlock() { return new CryptoBlock(0, "01/01/2020", "Initial Block in the Chain", "0"); } obtainLatestBlock() { return this.blockchain[this.blockchain.length - 1]; } addNewBlock(newBlock) { newBlock.precedingHash = this.obtainLatestBlock().hash; //newBlock.hash = newBlock.computeHash(); newBlock.proofOfWork(this.difficulty); this.blockchain.push(newBlock); } checkChainValidity() { for (let i = 1; i < this.blockchain.length; i++) { const currentBlock = this.blockchain[i]; const precedingBlock = this.blockchain[i - 1]; if (currentBlock.hash !== currentBlock.computeHash()) { return false; } if (currentBlock.precedingHash !== precedingBlock.hash) return false; } return true; } } let smashingCoin = new CryptoBlockchain(); console.log("smashingCoin mining in progress...."); smashingCoin.addNewBlock( new CryptoBlock(1, "01/06/2020", { sender: "Iris Ljesnjanin", recipient: "Cosima Mielke", quantity: 50 }) ); smashingCoin.addNewBlock( new CryptoBlock(2, "01/07/2020", { sender: "Vitaly Friedman", recipient: "Ricardo Gimenes", quantity: 100 }) ); console.log(JSON.stringify(smashingCoin, null, 4));
Si ejecuto el código en la terminal, este es el resultado que obtengo:
Como puede ver en la imagen de arriba, los hashes ahora comienzan con cuatro ceros, que se corresponden con el nivel de dificultad establecido en el mecanismo de prueba de trabajo.
Conclusión
¡Eso es todo! Así es como puede construir una cadena de bloques de criptomonedas simple usando Node.js.
Por supuesto, la criptomoneda smashingCoin
está lejos de estar completa. De hecho, si lo lanza sin realizar más mejoras, es poco probable que satisfaga las demandas actuales del mercado de una moneda digital segura, confiable e intuitiva, ¡lo que lo convierte en el único que la usa!
No obstante, espero que este tutorial lo haya equipado con algunas habilidades básicas para mojarse los pies en el emocionante mundo de las criptomonedas.
Si tiene algún comentario o pregunta, por favor publíquelo a continuación.
Más recursos
- "Cadena de bloques 101", CoinDesk
- "Bitcoin: un sistema de efectivo electrónico punto a punto", Satoshi Nakamoto, Bitcoin.org