Last active
February 12, 2018 08:46
-
-
Save walexi/3c966f18e4f78a50e3d7e8e554ba3030 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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