Block Chain - Utility Functions

This will be a comparitively longer tutorial. We will create a data structure to store block chain, write functions to mine new blocks, check validity of the block chain, calculate hash etc. Proof of work needs a bit of explanation so I will dedicate the next tutorial to proof of work.

A block chain is a chain of block where each block is linked to the previous one and contains some data. Each block contains the hash of previous block and its own data attributes. This way hashes are propagated in a block chain.

We will use a javascript class to create blocks. The structure of a block will be as follows:

Block{
Index: 'Stores the index of the block';
Previous Hash: 'Hash value stored in previous block';
Timestamp: 'Stores timestamp of block creation';
Data: 'Data to be stored';
Hash: 'Hash value of all the attributes of current block';
Nonce: 'Some value to make the hash value of this block satisfy specific conditions(used in proof of work)';
}

Firstly, import the required packges.

var CryptoJS = require("crypto-js");

Now add the following code to index.js for Block class.

class block{
constructor(index, previousHash, timeStamp, data, hash, nonce)
{
this.index = index;
this.previousHash = previousHash.toString();
this.timeStamp = timeStamp;
this.data = data;
this.hash = hash.toString();
this.nonce = nonce;
}
};

Create an array to save the block chain. An array is used because data order is maintained in an array.

var blockChain = [];

The first block in a block chain is called Genesis Block. It has constant values for index,timeStamp, previousHash, data and nonce. Create a function to get genesis block and a function to calculate hash. Then call the getGenesisBlock function while creating the block chain.

function getHash(index, timeStamp, data, previousHash, nonce){
index = index.toString();
timeStamp = timeStamp.toString();
data = data.toString();
previousHash = previousHash.toString();
nonce = nonce.toString();
return CryptoJS.SHA256( index + timeStamp + data + previousHash + nonce );
}

function getGenesisBlock(){
var timeStamp = 1511259811865/1000;
return new block(0, "0", timeStamp, "Hello World", getHash(0, "0", timeStamp, "Hello World", 1),1);
}

var blockChain = [ getGenesisBlock() ];

Now, we need a function to add new blocks to the block chain. This function will accept some data and add a block to the block chain.

function addBlock(data){
if( data == undefined || data == "" )
console.log("No data found.");
else
{
var timeStamp = new Date().getTime()/1000;
var previousBlock = blockChain[blockChain.length-1];
var hash = getHash( previousBlock.index + 1, previousBlock.hash, timeStamp, data, nonce );
var nonce = 0; //will get value in proof of work
var temp = new block( previousBlock.index + 1, previousBlock.hash, timeStamp, data, hash, nonce );
blockChain.push(temp);
console.log("New Block Added");
}
}

verifyBlockChain verifies whether the block chain is valid or not. It checks that the hash values are consistent. In next tutorial, we will check the proof of work condition also in this function.

function verifyBlockChain(chain){
var flag = 1;
for(var i=0;i<chain.length-1;i++)
{
let h = getHash(chain[i].index, chain[i].previousHash, chain[i].timeStamp, chain[i].data, chain[i].nonce);
if( chain[i+1].previousHash != h )
{
console.log(i);
console.log(h);
flag = 0;
break;
}
}
return flag;
}

Nodes broadcast there blockchain to other nodes if a new block is added to the block chain or on request of other node. In this case, the other node will compare its own block chain with the received block chain. The longer block chain is accepted and thus prevails. Therefore a function compareBlockChains is created which will compare two block chains.

function compareBlockChain(chain, receivedChain){
if(chain.length < receivedChain.length){
var flag = 1;
//genesis block should not be compared
for(let j=1; j< chain.length; j++)
{
if(chain[j] != receivedChain[j])
{
flag = 0;
break;
}
}
return flag;
}
else
{
return false; // Received Block Chain is shorter.
}
}

Finally index.js looks something like this.

'use strict'
var express = require('express');
var bodyParser = require('body-parser');
var path = require('path');
var WebSocket = require('ws');
var CryptoJS = require("crypto-js");
var app = express();

app.set('http_port', 4001);
app.set('p2p_port', 4002);

var server = app.listen(app.get('http_port'), function(){
console.log("Server is running on port ", app.get('http_port'));
});
var webServer = new WebSocket.Server({ port: app.get('p2p_port')}, function(){
console.log('P2P server, port: ' + app.get('p2p_port'));
});

class block{
constructor(index, previousHash, timeStamp, data, hash, nonce)
{
this.index = index;
this.previousHash = previousHash.toString();
this.timeStamp = timeStamp;
this.data = data;
this.hash = hash.toString();
this.nonce = nonce;
}
};

function getHash(index, timeStamp, data, previousHash, nonce){
index = index.toString();
timeStamp = timeStamp.toString();
data = data.toString();
previousHash = previousHash.toString();
nonce = nonce.toString();
return CryptoJS.SHA256(index+timeStamp+data+previousHash+nonce);
}

function getGenesisBlock(){
var timeStamp = 1511259811865/1000;
return new block(0, "0", timeStamp, "Hello World", getHash(0, "0", timeStamp, "Hello World", 1),1);
}

var blockChain = [ getGenesisBlock() ];

function addBlock(data){
if( data == undefined || data == "" )
console.log("No data found.");
else
{
var timeStamp = new Date().getTime()/1000;
var previousBlock = blockChain[blockChain.length-1];
var nonce = 0; //will get value in proof of work
var hash = getHash( previousBlock.index + 1, previousBlock.hash, timeStamp, data, nonce );
var temp = new block( previousBlock.index + 1, previousBlock.hash, timeStamp, data, hash, nonce );
blockChain.push(temp);
console.log("New Block Added");
}
}

function verifyBlockChain(chain){
var flag = 1;
for(var i=0;i<chain.length-1;i++)
{
let h = getHash(chain[i].index, chain[i].previousHash, chain[i].timeStamp, chain[i].data, chain[i].nonce);
if( chain[i+1].previousHash != h )
{
console.log(i);
console.log(h);
flag = 0;
break;
}
}
return flag;
}

app.get("/", function(request, response){
response.send("Hello Block Chain");
});

//Print hello world
console.log("Hello World");

Now test the code which we just wrote by writing following lines of code at the end of the file.

addBlock("This is block two");
console.log(blockChain);

Again run the file using either of the following commands:

nodejs index.js
node index.js

Next -> Block Chain - Proof of Work

Previous -> Block Chain - Server Setup


Comments