almacenando bloques en Leveldb
Si ejecutas tu blockchain durante unas horas, notarás que el número de bloques creados crece, lo que puede convertirse en un problema ya que actualmente los bloques se almacenan en la memoria caché de su computadora. A medida que agrega más y más bloques, el uso de memoria aumentará y, finalmente, su código fallará. Además, sin almacenar sus bloques en una base de datos, no serás capaz de iniciar y detener tu red P2P, ya que los bloques no se guardan. Para adaptarse a estos casos de uso y otros, utilizará una base de datos LevelDB.
Una base de datos de LevelDB almacena pares de nombre-valor. Es una opción ideal para blockchain. De hecho, bitcoin usa LevelDB para almacenar no solo bloques, sino también información de transacciones. Consulta https://github.com /bitcoin-core /leveldb.
leveldb
En este post, implementaremos una base de datos para almacenar sus bloques. Ejecuta:
> npm install level -save
Crea un direcitorio llamado db:
> mkdir db
Ahora puede implementar la base de datos. En su librearia chain.js, agregua código para guardar su bloque en la base de datos de LevelDB, como se muestra abajo:
let level = require('level'),
fs = require('fs');
let db;
let createDb = (peerId) => {
let dir = __dirname + '/db/' + peerId;
if (!fs.existsSync(dir)){
fs.mkdirSync(dir);
db = level(dir);
storeBlock(getGenesisBlock());
}
}
Como puede ver, usa la clase nativa __dirname del nucleo de Node.js para darle la
ubicación de la ruta del directorio porque necesita la ruta completa para guardar su base de datos. Debido a que está ejecutando varias instancias de su red P2P en la misma
máquina, no puede utilizar la misma ruta para cada peer porque la base de datos
necesita estar separada. Lo que puede hacer es establecer la ubicación de cada base de datos en una ubicación de ruta separada usando el nombre de la carpeta como el nombre de su ID de peer; luego cada base de datos se puede almacenar en la carpeta db. También observe que guardas el primer bloque, getGenesisBlock ().
Ahora, crea un metodo llamado storeBlock para almacenar el nuevo bloque:
let storeBlock = (newBlock) => {
db.put(newBlock.index, JSON.stringify(newBlock), function (err) {
if (err) return console.log('Ooops!', err) // some kind
of I/O error
console.log('--- Inserting block index: ' + newBlock.
index);
})
}
Cuando generas un nuevo bloque utilizando el método generateNextBlock, lo almacenas en la base de datos de LevelDB.
storeBlock(newBlock);
También va a agregar un método para poder recuperar un bloque de la Base de datos LevelDB.
let getDbBlock = (index, res) => {
db.get(index, function (err, value) {
if (err) return res.send(JSON.stringify(err));
return(res.send(value));
});
}
Asegúrate de exponer los métodos createDb y getDbBlock.
if (typeof exports != 'undefined' ) {
exports.createDb = createDb;
exports.getDbBlock = getDbBlock;}
Por último, en su código de red P2P, todo lo que necesita hacer es crear una base de datos una vez comienza el codigo:
chain.createDb(myPeerId.toString('hex'));
Para ver el código en acción, ejecute una instancia de la red P2P:
> node p2p.js
Puede monitorear los datos de la base de datos en la carpeta db usando el comando tail
con el flag -f. La terminal permanecerá abierta y podrá mostrarle nuevos bloques a medida que se están generando:
> cd step4/db/[our peer Id]
> tail –f 000003.log
En este post, creó una base de datos de LevelDB. Estás almacenando tus bloques por lo que podrá recuperarlos en lugar de depender de su memoria caché. Manteniendo las cosas simples, si se tratara de una blockchain de producción, implementamos los siguientes pasos:
- Mitigua todos los posibles riesgos de seguridad.
- Almacena y recupera tus bloques de la base de datos de LevelDB.
- Crea un método para restaurar las entradas de LevelDB.
- Limpia las bases de datos antiguas porque se crean nuevas en
cada init.