Skip to content

Instantly share code, notes, and snippets.

@walexi
Last active February 12, 2018 08:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save walexi/3c966f18e4f78a50e3d7e8e554ba3030 to your computer and use it in GitHub Desktop.
Save walexi/3c966f18e4f78a50e3d7e8e554ba3030 to your computer and use it in GitHub Desktop.
const hash = require("crypto-js/sha256");
/**
* Block class implements a typical block in the chain, has all the methods calculateHash and mineBlock and a constructor method to
* initialize the properties of the block
*/
class Block {
/**
* [constructor method to initialize the properties of the block]
* @param {[Number]} index [the position of the block in the chain]
* @param {[String]} timestamp [timestamp in the format DD/MM/YYYY]
* @param {[Object]} data [data the block stores/holds]
* @param {[String]} previoushash [the hash of the previous block, 0 if its the first block (Genesis block)]
* @param {[String]} hash [the hash of the current block]
* @param {{Number}} nounce [the nounce is used to track the iteration involved in mining a new block in the mineBlock method]
*/
constructor(index, timestamp, data, previoushash = " "){
this.index = index;
this.timestamp = timestamp;
this.data = data;
this.previoushash = previoushash;
this.hash = this.calculateHash();
this.nounce = 0;
}
/**
* [calculateHash method to calculate the hash of the block from the index, timestamp, data, previousHash and nounce properties]
* @return {[String]} [returns the hash value in string format]
*/
calculateHash(){
return hash(this.index + this.timeStamp + JSON.stringify(this.data).toString() + this.previoushash + this.nounce).toString();
}
/**
* [mineBlock method to mine a block, it ensures the computed hash
* of the block starts with a number of zeroes that
* is equal to the difficulty parameter. The nounce variable is used to track
* he iteration]
* @param {[Number]} difficulty [the number of leading zeroes in the computed hash of the block]
*/
mineBlock(difficulty){
while(this.hash.substring(0, difficulty) !== Array(difficulty + 1).join("0")){
this.nounce++;
this.hash = this.calculateHash();
}
}
}
/**
* BlockChain class implements the blockchain and implements the following methods: createGenesisBlock, getLatestBlock, addBlock, isChainValid;
* and a constructor method to initialize the chain and the difficulty level associated with mining a block in this particular chain
*/
class Blockchain {
/**
* [constructor method to initialize the chain array and difficulty level. The chain array is initialized with the
* first block in the chain which is returned from the createGenesis method call.]
*/
constructor(difficultyLevel){
this.chain = [this.createGenesisBlock()];
this.difficulty = difficultyLevel;
}
/**
* [createGenesisBlock method to create the first block in a chain setting the previousHash to 0]
* @return {[Block]} [a new block]
*/
createGenesisBlock(){
return new Block(0, "14/01/2018", "Genesis Block", "0");
}
/**
* [getLatestBlock method to retrieve the last block that was added to the chain]
* @return {[Block]} [the last block that was added to the chain]
*/
getLatestBlock(){
return this.chain[this.chain.length -1];
}
/**
* [addBlock method to add a new block to the chain. It sets the previousHash properties, calls the mineBlock method of the Block Object,
* and pushes the new block to the end of the chain]
*/
addBlock(newblock){
newblock.previoushash = this.getLatestBlock().hash;
newblock.mineBlock(this.difficulty);
this.chain.push(newblock);
}
/**
* [isChainValid method to verify the integrity or validity of the blockchain by performing the following checks:
* -- checks the validity of the hash value of the block
* -- checks if the previousHash property of the current block is ]
* @return {Boolean} [whether the chain is valid or not: True of False]
*/
isChainValid(){
for(let i = 1; i < this.chain.length; i++){
const currentBlock = this.chain[i];
const prevBlock = this.chain[i-1];
if(currentBlock.hash !== currentBlock.calculateHash()){
return false;
}
if(currentBlock.previoushash !== prevBlock.hash){
return false;
}
}
return true;
}
}
/**
* How to run this code:
*
* 1. Install the module (preferably globally) with this command in your commanline
*
* npm install -g crypto-js
* yarn add global crypto-js
*
* or any package manager of your choice.
* 2. To run the code below simply run this file with the command below
* node main.js
*
*
*/
let blc = new Blockchain(4); // create a new blockchain - an instance of the BlockChain class
blc.addBlock(new Block(1, "12/2/33",{amount: 56})); //add new blocks to the chain
blc.addBlock(new Block(2, "13/2/33",{amount: 34}));
blc.addBlock(new Block(3, "14/2/33",{amount: 20}));
console.log(blc.isChainValid()); //checks and print the validity of the chain
console.log(JSON.stringify(blc, null, 4))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment