Thursday, January 11, 2018

A Simple Blockchain in JavaScript

// To run this, do this at a bash shell:
// node main.js

// Source: https://www.youtube.com/watch?v=zVqczFZr124

// Ran this to use SHA56: npm install --save crypto-js

const SHA256 = require('crypto-js/sha256');

class Block {
  constructor(index, timestamp, data, previousHash = '') {
    this.index = index;
    this.timestamp = timestamp;
    this.data = data;
    this.previousHash = previousHash;
    this.hash = this.calculateHash();
  }

  calculateHash() {
    return SHA256(this.index + this.previousHash + this.timestamp +
      JSON.stringify(this.data)).toString();
  }
}

class Blockchain {
  constructor() {
    this.chain = [this.createGenesisBlock()];
  }

  createGenesisBlock() {
    return new Block(0, '1/1/2018', 'Genesis block', '0');
  }

  getLatestBlock() {
    return this.chain[this.chain.length - 1];
  }

  addBlock(newBlock) {
    newBlock.previousHash = this.getLatestBlock().hash;
    newBlock.hash = newBlock.calculateHash();
    this.chain.push(newBlock);
  }

  isChainValid() {
    // Don't need to check the genesis block
    for(let i = 1; i < this.chain.length; i++) {
      const currentBlock = this.chain[i];
      const previousBlock = this.chain[i - 1];

      // Verify the hashes are correct
      if (currentBlock.hash !== currentBlock.calculateHash()) {
        return false;
      }

      // Verify the current block points to the correct previous block
      if (currentBlock.previousHash !== previousBlock.hash) {
        return false;
      }
    }
    return true;
  }
}

let blockchain = new Blockchain();
blockchain.addBlock(new Block(1, '1/2/2018', { amount: 4 }));
blockchain.addBlock(new Block(2, '1/3/2018', { amount: 10 }));

console.log(JSON.stringify(blockchain, null, 4));

console.log('Valid chain: ' + blockchain.isChainValid());

// Tamper with the blockchain by changing an amount
blockchain.chain[1].data = { amount: 100 };

console.log('Valid after tampering: ' + blockchain.isChainValid());