Let’s Create a BlockChain on Nodejs With MongoDB 03

Video Tutorial

Overview

In the last tutorial, we have integrated the MongoDB database into our blockchain application and improved the way to add a new block to the chain and mine it by hashing a random none number until you get to the right one and finally saved it on the database, while the main idea behind having a blockchain is each block get linked into the chain with a (previous hash) property that points to the hash of the last block on the chain this way we can make sure that all the chain is linked and secured, but this functionality still lucks in out blockchain node’s implementation.

If you are new around here, please make sure to watch the whole Blockchain’s series from the beginning in order to understand what we are actually doing here.

Getting Last Saved Block

The reason we need to get the last block is that we need to set the current block’s prevHash which will be added to the chain and saved on the database to the last block’s hash, therefore, we have to query the MongoDB database to look for the last block saved on the database, however if there is no block (new chain no block has been added yet) then it just gonna set it to null which basically means this is the first block on the chain and there is no block before it.

Let’s add a new getLastBlock method to the blockChain class.

/* blockchain.js */
class BlockChain {
...
getLastBlock(callback) {
  //Get last block from Database
  return BlockChainModel.findOne(
    {},
    null,
    { sort: { _id: -1 }, limit: 1 },
    (err, block) => {
      //in case of err just log it and return (stop execution)
      if (err) return console.error("Cannot get last block ", err.message);
      //get out of the function and run callback passing it the lastBlock 
      return callback(block);
    }
  );
}
...
}

getLastBlock method is responsible for querying the MongoDB database to find the last block and run a callback going passing it the block that has been found.

We sort the MongoDB by _id where giving a negative (sort: -1) value means that the database is going to start looking from the end up that’s how we can get the last block on the chain, in case if there is no block added yet MongoDB is going to return null for us so we have later to double check it and processed with the block saving.

Set Previous Hash

Now when we mine a new block we have to first get the last block from the database when using the callback we can ensure that the steps get executed the way it should otherwise you will get an error concerning the block is null or undefined.

...
if (validator.proofOfWork() == TARGET_HASH) {
            //Query for last block 
            this.getLastBlock((lastBlock) => {
              //only if the lastBlock exists (not null or undefined)
              if(lastBlock) {
                 //Link blocks together using hashes 
                 block.prevHash = lastBlock.hash;
              }
               //otherwise carry on with saving it into the DB.
               block.hash = hash(block);
               //Add it to the instance Save it on the DB Console Success
               let newBlock = new blockChainModel(block);
               newBlock.save((err) => {
                   if (err)
                       return console.log(chalk.red("Cannot save Block to DB ", err.message));
                   console.log(chalk.green("Block Saved on the DB"));
               });
               //Add to Chain
               this
                   .chain
                   .push(block);
               this.curr_transactions = [];
               return block;
       })
}
...

When the block is ready to be saved (mined successfully) we first query the database for the lastBlock and we need to register a callback for it to run as expected since MongoDB works asynchronously, therefore, everything needs to be registered in callbacks in order to make sure that steps get executed as the order it should.

We also have to double check that the lastBlock is valid cause when MongoDB doesn’t find what request (for ex: the chain is empty no blocks are added yet) it will return null so we have to make sure it valid otherwise just carry on with the saving and let the prevHash to be null since it’s the first block in the chain.

The moment of truth let’s run the blockchain demo and try to mine one or two blocks to see if it actually fits into the database as expected or not.

node ./main.js

Wait for the mining to finish then open MongoDB Compass to take a look on the documents on the database you should notice that the last block is pointing (prevHash) to the block’s hash right before it on the chain.

What’s Next

From this point you can take this blockchain basic implementation one step forward and add more features and functionalities like more real proof of work to make sure the block is valid and storing custom data on the blocks alongside the basic data and many other exciting things you can do with blockchain technologie, let me know if you recommend implementing any feature or function.

No Comments Yet